home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Storage / DragDrp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-13  |  95.0 KB  |  3,081 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DragDrp.cpp
  3.  
  4.     Contains:    Implementation of ODDragAndDrop
  5.  
  6.     Owned by:    Douglas Hill
  7.     
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <22>      11/13/96    DH        Bug#1402328:Added API for Container Apps to
  13.                                     process drags for embedding manually
  14.                                     without using OpenDoc drag handlers.
  15.         <21>      10/23/96    DH        Fixed dragging to the Finder.
  16.         <20>      10/22/96    DH        1395783    •ODDrag and Drop caches the
  17.                                     windowState. Keeps ODIA happy by getting a
  18.                                     new copy everytime we need it.;1397986    •
  19.                                     Mismatch between FSpOpenRefFile and
  20.                                     FSClose; 1380627    • Draging an embedded part
  21.                                     to finder can fail. Now truncates the
  22.                                     filename of drag of an embedded part to the
  23.                                     max size of the OS.
  24.         <19>     9/19/96    DH        Task: low memory changes. Suppress fatal
  25.                                     Bento errors during low-mem D&D problems.
  26.         <18>     8/13/96    DM        1376080: use TempDelayBentoFatalError to
  27.                                     ensure old flag value is restored
  28.         <17>     7/18/96    DH        Task: Self-embedding causes crash. Fixed
  29.                                     exception handling in drag receive handler
  30.                                     so return value of Drop is propogated
  31.                                     correctly.
  32.         <16>     7/11/96    DH        1365986    1.1GM: Crash when drag fails and
  33.                                     another drag is attempted. Fixed many stale
  34.                                     object references.
  35.         <15>     6/26/96    DH        #1358088: Subframes allow self-embedding.
  36.                                     This was a part of a more general case of
  37.                                     nested self-embedding. Fixed so that the
  38.                                     checks happen at drag-tracking time
  39.                                     correctly. See also new recipe for marking
  40.                                     frames as part of a drag.
  41.         <14>     6/21/96    DH        1340739: 1.0.xp: Ctl-drag of content to
  42.                                     non-od destination does not remove
  43.                                     original.
  44.                                     1340966: 1.0.x: Avoiding undo when content
  45.                                     dragged to non-OpenDoc target. 1340739:
  46.                                     1.0.xp: Ctl-drag of content to non-od
  47.                                     destination does not remove original.
  48.                                     1353507: 1.0.x: Dragging Scrapbook OpenDoc
  49.                                     clipping to document can cause crash. Added
  50.                                     support for reading clipping files (see
  51.                                     ODDragAndDropEnterHandler).
  52.         <13>     5/31/96    jpa        T10012: Overhauled IsOpenDocDocument. Set
  53.                                     correct creator of files/promises created.
  54.         <12>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  55.         <11>     5/13/96    DH        1332488 - 1.0.x:User break dragging Edition
  56.                                     file into an OpenDoc window.
  57.                                     1305572 - 1.1MRD:[Cyberdog]Dragging
  58.                                     multiple items *really* slow.
  59.                                     1314704 - 1.0.x: Enourmous performance hit
  60.                                     when dragging numerous items over windows.
  61.         <10>      5/1/96    JA        1314704: Create only one mem container
  62.                                     (_fMemItemContainer) for all dragged-in
  63.                                     non-Bento files.
  64.          <9>    .04.1996    NP        1330731: Don't use stationery property
  65.                                     anymore.
  66.          <8>     4/16/96    DH        Fixed InWindow to ignore a null container.
  67.          <7>      4/9/96    DH        1308248: 1.0.2 Drag of no-part to trash
  68.                                     rejected. Used string resource for no-part
  69.                                     category instead of hard-coding it. Also
  70.                                     made filename of file in Trash when you
  71.                                     drop Nopart into the trash not be garbled.
  72.          <6>      4/8/96    DH        1338112: 1.0.2? Drag Hiliting Problems
  73.          <4>     3/29/96    DM        1296171: delay fatal Bento container errors
  74.                                     when inside drag manager
  75.          <3>     3/15/96    VL        1302780: Use GetFacetUnderPointForDrag
  76.                                     instead of GetFacetUnderPoint so that we
  77.                                     can drop within selection.
  78.          <2>     3/15/96    DH        287259 - 1.0.2 Don't get back what I put in
  79.                                     the scrapbook. Now writes out a memory
  80.                                     container to applications that it reloads
  81.                                     if it is found from Drag and Drop. Also
  82.                                     compatible with Clipboard container type.
  83.                                     1293781 - 1.0.2 DragWithin called out of
  84.                                     order. Fixed ODDragAndDropInWindow so that
  85.                                     it doesn't call DragLeave on the Containing
  86.                                     part unless the embedded part returns True
  87.                                     from DragEnter.
  88.  
  89.     To Do:        
  90.     In Progress:
  91.         
  92. */
  93.  
  94. #ifndef _ALTPOINT_
  95. #include "AltPoint.h"            // Use C++ savvy ODPPoint and ODPRect
  96. #endif
  97.  
  98. #define ODDragAndDrop_Class_Source
  99. #define VARIABLE_MACROS
  100. #include <DragDrp.xih>
  101.  
  102. #ifndef SOM_ODDragItemIterator_xh
  103. #include <DgItmIt.xh>
  104. #endif
  105.  
  106. #ifndef _DRAGPRIV_
  107. #include <DragPriv.h>
  108. #endif
  109.  
  110. #ifndef _STORRSRC_
  111. #include <StorRsrc.h>
  112. #endif
  113.  
  114. #ifndef SOM_Module_OpenDoc_StdProps_defined
  115. #include <StdProps.xh>
  116. #endif
  117.  
  118. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  119. #include <StdTypes.xh>
  120. #endif
  121.  
  122. #ifndef SOM_ODSession_xh
  123. #include <ODSessn.xh>
  124. #endif
  125.  
  126. #ifndef SOM_ODStorageSystem_xh
  127. #include <ODStor.xh>
  128. #endif
  129.  
  130. #ifndef SOM_ODContainer_xh
  131. #include <ODCtr.xh>
  132. #endif
  133.  
  134. #ifndef SOM_ODDocument_xh
  135. #include <Document.xh>
  136. #endif
  137.  
  138. #ifndef SOM_ODDraft_xh
  139. #include <Draft.xh>
  140. #endif
  141.  
  142. #ifndef SOM_ODFrame_xh
  143. #include <Frame.xh>
  144. #endif
  145.  
  146. #ifndef SOM_ODFacet_xh
  147. #include <Facet.xh>
  148. #endif
  149.  
  150. #ifndef SOM_ODWindow_xh
  151. #include <Window.xh>
  152. #endif
  153.  
  154. #ifndef SOM_ODWindowState_xh
  155. #include <WinStat.xh>
  156. #endif
  157.  
  158. #ifndef SOM_ODPart_xh
  159. #include <Part.xh>
  160. #endif
  161.  
  162. #ifndef SOM_ODTransform_xh
  163. #include <Trnsform.xh>
  164. #endif
  165.  
  166. #ifndef SOM_ODTranslation_xh
  167. #include <Translt.xh>
  168. #endif
  169.  
  170. #ifndef _ODMEMORY_
  171. #include "ODMemory.h"
  172. #endif
  173.  
  174. #ifndef _ODNew_
  175. #include "ODNew.h"
  176. #endif
  177.  
  178. #ifndef _EXCEPT_
  179. #include "Except.h"
  180. #endif
  181.  
  182. #ifndef _LINKLIST_
  183. #include "LinkList.h"
  184. #endif
  185.  
  186. #ifndef SOM_ODStorageUnitView_xh
  187. #include <SUView.xh>
  188. #endif
  189.  
  190. #ifndef _BENTOSUPPRESS_
  191. #include "BentoSuppress.h"
  192. #endif
  193.  
  194. #ifndef _STORDEF_
  195. #include "StorDef.h"
  196. #endif
  197.  
  198. #ifndef SOM_CMStorageUnit_xh
  199. #include <CMSU.xh>
  200. #endif
  201.  
  202. #ifndef _PLFMFILE_
  203. #include <PlfmFile.h>
  204. #endif
  205.  
  206. #ifndef _CONSTDEF_
  207. #include "ConstDef.h"
  208. #endif
  209.  
  210. #ifndef _PASCLSTR_
  211. #include <PasclStr.h>
  212. #endif
  213.  
  214. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  215. #include "StdDefs.xh"
  216. #endif
  217.  
  218. #ifndef _LINKDLGS_
  219. #include "LinkDlgs.h"
  220. #endif
  221.  
  222. #ifndef __MEMORY__
  223. #include <Memory.h>
  224. #endif
  225.  
  226. #ifndef __GESTALTEQU__
  227. #include <GestaltEqu.h>
  228. #endif
  229.  
  230. #ifndef __TOOLUTILS__
  231. #include <ToolUtils.h>
  232. #endif
  233.  
  234. #ifndef __ERRORS__
  235. #include <Errors.h>
  236. #endif
  237.  
  238. #ifndef __SCRIPT__
  239. #include <Script.h>
  240. #endif
  241.  
  242. #ifndef __PACKAGES__
  243. #include <Packages.h>
  244. #endif
  245.  
  246. #ifndef __APPLEEVENTS__
  247. #include <AppleEvents.h>
  248. #endif
  249.  
  250. #ifndef _ISOSTR_
  251. #include <ISOStr.h>
  252. #endif
  253.  
  254. #ifndef __ALIASES__
  255. #include <Aliases.h>
  256. #endif
  257.  
  258. #ifndef __FOLDERS__
  259. #include <Folders.h>
  260. #endif
  261.  
  262. #ifndef _BARRAY_
  263. #include <BArray.h>
  264. #endif
  265.  
  266. #ifndef SOM_ODNameSpaceManager_xh
  267. #include <NmSpcMg.xh>
  268. #endif
  269.  
  270. #ifndef SOM_ODValueNameSpace_xh
  271. #include <ValueNS.xh>
  272. #endif
  273.  
  274. #ifndef _TEMPOBJ_
  275. #include <TempObj.h>
  276. #endif
  277.  
  278. #ifndef _STORUTIL_
  279. #include "StorUtil.h"
  280. #endif
  281.  
  282. #include <string.h>
  283.  
  284. #ifndef _ODDEBUG_
  285. #include "ODDebug.h"
  286. #endif
  287.  
  288. #ifndef _NMSPCUTL_
  289. #include <NmSpcUtl.h>
  290. #endif
  291.  
  292. #ifndef _STDTYPIO_
  293. #include <StdTypIO.h>
  294. #endif
  295.  
  296. #ifndef __DIALOGS__
  297. #include <Dialogs.h>
  298. #endif
  299.  
  300. #ifndef _INFOUTIL_
  301. #include <InfoUtil.h>
  302. #endif
  303.  
  304. #ifndef __ICONS__
  305. #include <Icons.h>
  306. #endif
  307.  
  308. #ifndef __FINDER__
  309. #include <Finder.h>
  310. #endif
  311.  
  312. #ifndef _POUTILS_
  313. #include <POUtils.h>
  314. #endif
  315.  
  316. #ifndef _OPENHASH_
  317. #include <OpenHash.h>
  318. #endif
  319.  
  320. #ifndef _ITEXT_
  321. #include <IText.h>
  322. #endif
  323.  
  324. #ifndef _USERSRCM_
  325. #include <UseRsrcM.h>
  326. #endif
  327.  
  328. #ifndef _DLOGUTIL_
  329. #include <DlogUtil.h>
  330. #endif
  331.  
  332. #ifndef _DRGDPDEF_
  333. #include "DrgDpDef.h"
  334. #endif
  335.  
  336. #ifndef __DIALOGS__
  337. #include <Dialogs.h>
  338. #endif
  339.  
  340. #ifndef _CTYPE
  341. #include <ctype.h>
  342. #endif
  343.  
  344. static FSSpec gTmpFileFSSpec;
  345. static FSSpec gTargetFSSpec;
  346. static boolean gIsResolvingPromise = kODFalse;
  347.  
  348. //==============================================================================
  349. // Prototyping
  350. //==============================================================================
  351.  
  352. extern ODBoolean gODBentoFatalErrorHasOccurred; // SessHdr.cpp
  353. extern ODBoolean gODDelayBentoFatalError; // SessHdr.cpp
  354. extern ODBoolean gODSuppressBentoFatalError; // SessHdr.cpp
  355. extern void ODBentoFatalError(ODBoolean allowSuppress); // SessHdr.cpp
  356.  
  357. static pascal OSErr MyDragTrackingHandler(
  358.         short message,
  359.         WindowPtr theWindow,
  360.         void* handlerRefCon,
  361.         ODPlatformDragReference theDrag);
  362.  
  363. static pascal OSErr    MyReceiveDropHandler(
  364.         WindowPtr theWindow,
  365.         void* handlerRefCon,
  366.         ODPlatformDragReference theDrag);
  367.  
  368. static pascal OSErr  MySendDataProc(
  369.         FlavorType theType,
  370.         void* refCon,
  371.         ItemReference theItem,
  372.         ODPlatformDragReference theDrag);
  373.  
  374. static OSErr ODPascal ReplaceFileAEHandler(
  375.         const AppleEvent* replaceFileEvent,
  376.         AppleEvent* reply,
  377.         long refCon);
  378.  
  379. static void RespecifyToTempFolder(PlatformFile* file);
  380. static OSErr CreateReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, ODSession* session, ProcessSerialNumber* psn);
  381. static OSErr SetupReplaceFileEvent(Environment* ev, AppleEvent* replaceFileEvent, FSSpec* sourceFileSpec, FSSpec* destFileSpec);
  382. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn);
  383. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent);
  384. static ODBoolean DragItemHasFlavor(ODPlatformDragReference theDrag, ItemReference itemID, OSType    theType);
  385. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec);
  386. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  387.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  388.                                 FSSpec dropFSSpec);
  389. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec *spec );
  390. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su );
  391. static OSErr CopyToDragItemInChunks(Environment* ev,
  392.                                 FlavorType theType,
  393.                                 ItemReference theItem,
  394.                                 ODPlatformDragReference theDrag,
  395.                                 ODDragItem* theDragItem);
  396. static OSErr CopyFromDragItemInChunks(Environment* ev,
  397.                                 FlavorType theType,
  398.                                 ItemReference theItem,
  399.                                 ODPlatformDragReference theDrag,
  400.                                 ODStorageUnitView* destSUView);
  401.  
  402. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  403.                                 ODSession* theSession,
  404.                                 FlavorType theType,
  405.                                 ItemReference theItem,
  406.                                 ODPlatformDragReference theDrag,
  407.                                 ODDragItem* theDragItem);
  408.  
  409. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession );
  410. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file);
  411. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file);
  412. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec& dropFSSpec);
  413. static boolean IsTrashFolder(FSSpec dropFSSpec);
  414. static boolean IsFrontProcess();
  415. static ODBoolean IsOpenDocClipping( HFSFlavor* hfsFlavor);
  416. static ODHandle ReadOpenDocDataFromClippingFile( HFSFlavor* hfsFlavor );
  417. static ODBoolean IsNestedSelfEmbedding( ODDragAndDrop *somSelf, Environment *ev, ODFrame* destFrame );
  418.  
  419. #ifdef ODDebug_DragAndDrop
  420.  
  421. #ifndef SOM_ODStorageUnitCursor_xh
  422. #include <SUCursor.xh>
  423. #endif
  424.  
  425. void PrintDragReference(ODPlatformDragReference dragRef, char* header);
  426. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header);
  427. #endif
  428.  
  429. #pragma segment ODDragAndDrop
  430.  
  431. #include "DragDrpB.cpp"    // Platform-independent methods, if any
  432.  
  433.  
  434. SOM_Scope ODBoolean  SOMLINK ODDragAndDropShowPasteAsDialog(ODDragAndDrop *somSelf, Environment *ev,
  435.         ODBoolean canPasteLink,
  436.         ODPasteAsMergeSetting mergeSetting,
  437.         ODFacet* facet,
  438.         ODTypeToken viewType,
  439.         ODStorageUnit* contentSU,
  440.         ODPasteAsResult* result)
  441. {
  442.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  443.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropShowPasteAsDialog");
  444.  
  445.     SOM_TRY
  446.  
  447.     THROW_IF_NULL(facet, kODErrNullFacetInput);
  448.     THROW_IF_NULL(contentSU, kODErrIllegalNullStorageUnitInput);
  449.     THROW_IF_NULL(result, kODErrNullPasteAsResultInput);
  450.  
  451.     ODBoolean returnValue = ShowPasteAsDialog(
  452.                                 canPasteLink, 
  453.                                 mergeSetting,
  454.                                 (somSelf->GetDropResult(ev) == kODDropMove),
  455.                                 contentSU,
  456.                                 facet, 
  457.                                 viewType, 
  458.                                 result);
  459.  
  460.     return returnValue;
  461.  
  462.     SOM_CATCH_ALL
  463.     SOM_ENDTRY
  464.     return kODFalse;
  465. }
  466.  
  467. SOM_Scope void  SOMLINK ODDragAndDropInitDragAndDrop(ODDragAndDrop *somSelf, Environment *ev,
  468.         ODSession* session)
  469. {
  470.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  471.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInitDragAndDrop");
  472.  
  473. SOM_TRY
  474.  
  475.     _fSession = session;
  476.  
  477.     somSelf->InitObject(ev);
  478.     
  479.     long  gestaltResult;
  480.     OSErr result;
  481.  
  482.     // Get the current process for background drag
  483.     _fPSN = (ProcessSerialNumber*) ODNewPtr(sizeof(ProcessSerialNumber));
  484.     GetCurrentProcess(_fPSN);
  485.     
  486.     _fReplaceFileEvent = (AppleEvent*) ODNewPtr(sizeof(AppleEvent));
  487.     CreateReplaceFileEvent(ev,
  488.         _fReplaceFileEvent,
  489.         session,
  490.         _fPSN);
  491.  
  492.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  493.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  494.                                     sizeof(ODFacet*),
  495.                                     sizeof(ODFacet*));
  496.         
  497.     // Check if the drag manager is present
  498.     result = Gestalt(gestaltDragMgrAttr, &gestaltResult);
  499.     if (result != noErr)
  500.         THROW_M(result, "Error from Gestalt");
  501.  
  502.     // The mysterious 31 is the bit position as BitTst uses a convention opposite to MC68000
  503.     if (BitTst(&gestaltResult, (31 - gestaltDragMgrPresent)) == false) {
  504.         THROW_M(kODErrNoDragManager, "No drag manager present");
  505.     }
  506.     else {
  507.         // Install the default tracking handler for this application (session)
  508.         _fTrackingHandler = NewDragTrackingHandlerProc(&MyDragTrackingHandler);
  509.         result = InstallTrackingHandler(_fTrackingHandler, NULL, (void *) somSelf);
  510.         ASSERTM(result == noErr, result, "Error from InstallTrackingHandler");
  511.         
  512.         // Install the default receive handler for this application (session)
  513.         _fReceiveHandler = NewDragReceiveHandlerProc(&MyReceiveDropHandler);
  514.         result = InstallReceiveHandler(_fReceiveHandler, NULL, (void *) somSelf);
  515.         ASSERTM(result == noErr, result, "Error from InstallReceiveHandler");
  516.     
  517.         // Create a UPP for MySendDataProc which we will use later inside ::StartDrag
  518.         _fSendDataHandler = NewDragSendDataProc(MySendDataProc);
  519.     
  520.         _fWindowState = _fSession->GetWindowState(ev);
  521.     
  522.         _fStorageSystem = _fSession->GetStorageSystem(ev);
  523.     
  524.         _fDragItemList = new LinkedList;
  525.  
  526.         AEEventHandlerUPP theHandlerUPP = NewAEEventHandlerProc( ReplaceFileAEHandler ) ;
  527.         THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  528.                 kODReplaceFileEventID, theHandlerUPP, nil, false));
  529.     }
  530.  
  531. SOM_CATCH_ALL
  532.  
  533.     _fWindowState = kODNULL;
  534.     _fStorageSystem = kODNULL;
  535.     if (_fDragItemList)
  536.     {
  537.         delete _fDragItemList;
  538.         _fDragItemList = kODNULL;
  539.     }
  540.     if (_fReceiveHandler)
  541.     {
  542.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  543.         DisposeRoutineDescriptor(_fReceiveHandler);
  544.         _fReceiveHandler = kODNULL;
  545.     }
  546.     if (_fTrackingHandler)
  547.     {
  548.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  549.         DisposeRoutineDescriptor(_fTrackingHandler);
  550.         _fTrackingHandler = kODNULL;
  551.     }
  552.     if (_fSendDataHandler)
  553.     {
  554.         DisposeRoutineDescriptor(_fSendDataHandler);
  555.         _fSendDataHandler = kODNULL;
  556.     }
  557.  
  558. SOM_ENDTRY
  559. }
  560.  
  561. SOM_Scope ODULong  SOMLINK ODDragAndDropGetDragAttributes(ODDragAndDrop *somSelf, Environment *ev)
  562. {
  563.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  564.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragAttributes");
  565.  
  566.     if (_fTrackingHandler == kODNULL)
  567.         ODSetSOMException(ev, kODErrNoDragManager);
  568.  
  569.     return _fAttributes;
  570. }
  571.  
  572. SOM_Scope ODPlatformDragReference  SOMLINK ODDragAndDropGetDragReference(ODDragAndDrop *somSelf, Environment *ev)
  573. {
  574.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  575.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragReference");
  576.  
  577.     if (_fTrackingHandler == kODNULL)
  578.         ODSetSOMException(ev, kODErrNoDragManager);
  579.         
  580.     return _fDragReference;
  581. }
  582.  
  583.  
  584. SOM_Scope ODFacet*  SOMLINK ODDragAndDropFindTargetFacet(ODDragAndDrop *somSelf, Environment *ev,
  585.         ODPlatformWindow theWindow,
  586.         ODPoint* mouse,
  587.         ODPoint* localMouse)
  588. {
  589.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  590.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropFindTargetFacet");
  591.  
  592.     ODFacet   *targetFacet = kODNULL;
  593.     
  594.     if (_fTrackingHandler == kODNULL)
  595.         ODSetSOMException(ev, kODErrNoDragManager);
  596.     else {
  597.         SOM_TRY
  598.             ODFacet   *curFacet;
  599.             GrafPtr        curPort;
  600.             Point        qdLocal;
  601.             
  602.             {    TempODWindow targetWindow = _fSession->GetWindowState(ev)->AcquireODWindow(ev,theWindow);
  603.                 if (!targetWindow)
  604.                     return kODNULL;
  605.             
  606.                 GetPort(&curPort);
  607.                 SetPort(theWindow);
  608.                 qdLocal = mouse->AsQDPoint();
  609.                 GlobalToLocal(&qdLocal);
  610.                 *localMouse = qdLocal;
  611.                 
  612.                 SetPort(curPort);
  613.             
  614.                 curFacet = targetWindow->GetFacetUnderPointForDrag(ev,
  615.                         localMouse);
  616.             }
  617.             
  618.             while (curFacet && !targetFacet)
  619.             {
  620.                 ODFrame* curFrame = curFacet->GetFrame(ev);
  621.                 #if ODDebug
  622.                     ODBoolean sample = kODFalse;
  623.                     sample = curFrame->IsDragging(ev);
  624.                     sample = curFrame->IsDroppable(ev);
  625.                     sample = curFrame->IsFrozen(ev);
  626.                     sample = IsNestedSelfEmbedding( somSelf, ev, curFrame );
  627.                     sample = _fFacetsRejected->Exists(&curFacet);
  628.                 #endif
  629.                 if (!curFrame->IsDragging(ev) &&
  630.                     curFrame->IsDroppable(ev) &&
  631.                     !curFrame->IsFrozen(ev) &&
  632.                     !IsNestedSelfEmbedding( somSelf, ev, curFrame ) &&
  633.                     !_fFacetsRejected->Exists(&curFacet))
  634.                 {
  635.                     targetFacet = curFacet;
  636.                 }
  637.                 curFacet = curFacet->GetContainingFacet(ev);
  638.             }
  639.             
  640.         SOM_CATCH_ALL
  641.         SOM_ENDTRY
  642.     }
  643.     return targetFacet;
  644. }
  645.  
  646. ODBoolean IsNestedSelfEmbedding( ODDragAndDrop *somSelf, Environment *ev, ODFrame* destFrame )
  647. {
  648. // Source frame: Frame that initiated the drag.
  649. // Destination frame: The frame where the drop will go. 
  650. // Indirect parent frame: A frame which is the parent of one of the parent's of an embedded
  651. // frame. It can be anywhere in the hierarchy of embedded frames above the embedded frame
  652. // in question.
  653. // Direct Embedded frame: An embedded frame whose containing frame is the source frame.
  654. // Nested embedded frame: An embedded frame whose indirect parent frame is embedded in the source frame.
  655.  
  656. // Want to check whether a drop destination is going to be in a nested embedded frame.
  657. // This will produce an infinite recursive situation when cloning.
  658.  
  659. // Note: We only need to check for nested self embedding, since single self embedding is already
  660. // covered by the IsDragging flag.
  661.  
  662. // Algorithm to check for self-embedding.
  663. //    1. Check if the destination frame's containing frame's IsDragging bit is set.
  664. //        A. If so return true. This is nested self-embedding.
  665. //    2. Set the current frame to the containing frame of the destination frame.
  666. //    3. If not, continue this iteration:
  667. //        A. Get the parent of the current frame and make it the current frame.
  668. //      B. If the current frame's IsDragging bit is set, return true.
  669. //        C. If the the current frame is null, return false. 
  670. //        D. If the the current frame == the source frame, return false. This means the frame was moved in the parent frame.
  671.  
  672.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  673.     ODBoolean loopDone = kODFalse;
  674.     ODBoolean selfEmbedding = kODFalse;
  675.     ODFrame* frameToBeReleased = kODNULL;
  676.  
  677.     ODFrame* sourceFrame = somThis->fSourceFrame;
  678.  
  679.     TRY
  680.         ODFrame* curFrame = destFrame->AcquireContainingFrame(ev);
  681.  
  682.         if( curFrame == kODNULL )
  683.         {
  684.             selfEmbedding = kODFalse;
  685.             loopDone = kODTrue;
  686.         }
  687.         else if( curFrame == sourceFrame )
  688.         {
  689.             selfEmbedding = kODFalse;
  690.             loopDone = kODTrue;
  691.         }
  692.         else if( curFrame->IsDragging(ev) == kODTrue)
  693.         {    
  694.             selfEmbedding = kODTrue;
  695.             loopDone = kODTrue;
  696.         }
  697.         frameToBeReleased = curFrame;
  698.         
  699.         while( !loopDone )
  700.         {
  701.             curFrame = curFrame->AcquireContainingFrame(ev); 
  702.             ODSafeReleaseObject( frameToBeReleased );
  703.             frameToBeReleased = curFrame;
  704.             if( curFrame == kODNULL )
  705.             {
  706.                 selfEmbedding = kODFalse;
  707.                 loopDone = kODTrue;
  708.             }
  709.             else if( curFrame == sourceFrame )
  710.             {
  711.                 selfEmbedding = kODFalse;
  712.                 loopDone = kODTrue;
  713.             }
  714.             else if( curFrame->IsDragging(ev) == kODTrue)
  715.             {    
  716.                 selfEmbedding = kODTrue;
  717.                 loopDone = kODTrue;
  718.             }
  719.         }
  720.     CATCH_ALL
  721.     ENDTRY
  722.     ODSafeReleaseObject( frameToBeReleased );
  723.     
  724.     return selfEmbedding;
  725. }
  726.  
  727. SOM_Scope void  SOMLINK ODDragAndDropGetPromiseFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  728.         ODPart* sourcePart,
  729.         ODStorageUnitView* destSUView)
  730. {
  731.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  732.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPromiseFromDragManager");
  733.  
  734.     SOM_TRY
  735.     
  736.     if (_fTrackingHandler == kODNULL)
  737.         THROW(kODErrNoDragManager);
  738.  
  739.     OSErr            err;
  740.     
  741.     if (sourcePart != kODNULL) {
  742.  
  743.         ItemReference    dragItemRef;
  744.         err = GetDragItemReferenceNumber(_fDragReference, 1, &dragItemRef);
  745.         ASSERTM(err == noErr, err, "Cannot get drag item reference in GetPromiseFromDragManager");
  746.  
  747.         ODPromiseDesc    theInfo;
  748.         theInfo.sourcePart = sourcePart;
  749.         theInfo.destSUView = destSUView;
  750.         
  751.         // Set the offset of the suview to the beginning of the value
  752.         destSUView->SetOffset(ev, 0);
  753.                 
  754.         AEDesc            dropLocation;
  755.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, sizeof(theInfo), &dropLocation);
  756.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  757.     
  758.         err = SetDropLocation(_fDragReference, &dropLocation);
  759.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  760.  
  761.         gIsResolvingPromise = kODTrue;
  762.  
  763.         long            resolveResult;
  764.         Size            resolveSize = sizeof(long);
  765.         
  766.         err = GetFlavorData(_fDragReference, dragItemRef, kODPromiseFlavor, &resolveResult, &resolveSize, 0);
  767.         ASSERTM(err == cantGetFlavorErr, err, "Cannot GetFlavorData in GetPromiseFromDragManager");
  768.         
  769.         AEDisposeDesc(&dropLocation);
  770.     
  771.         // Reset the Drop location.
  772.  
  773.         gIsResolvingPromise = kODFalse;
  774.         
  775.         theInfo.sourcePart = kODNULL;
  776.         theInfo.destSUView = kODNULL;
  777.         
  778.         err = AECreateDesc(kODPromiseDesc, (Ptr) &theInfo, 0, &dropLocation);
  779.         ASSERTM(err == noErr, err, "Error from AECreateDesc in GetPromiseFromDragManager");
  780.         
  781.         err = SetDropLocation(_fDragReference, &dropLocation);
  782.         ASSERTM(err == noErr, err, "Error from SetDropLocation in GetPromiseFromDragManager");
  783.         
  784.         AEDisposeDesc(&dropLocation);
  785.     }
  786.     else {
  787.         ODHandle dataHandle = kODNULL;
  788.         ODType isoType = kODNULL;
  789.         TRY
  790.         
  791.             ODTranslation*    translate  = _fSession->GetTranslation(ev);
  792.             isoType = destSUView->GetType(ev);
  793.             if (ODISOStrNCompare((ODISOStr) isoType,(ODISOStr) kODAppleFileTypePrefix, ODISOStrLength(kODAppleFileTypePrefix)) != 0) {
  794.                 ItemReference   theItem;
  795.                 OSErr result;
  796.                 destSUView->SetOffset(ev,0);
  797.                 StorageUnitViewGetValue(destSUView, ev, sizeof(ItemReference), &theItem);            
  798.                 ODPlatformType platformType = translate->GetPlatformTypeFromISOType(ev, isoType);            
  799.                 if ( platformType == kODScrapTypestxt && !DragItemHasFlavor(_fDragReference, theItem, kODScrapTypestxt) )
  800.                 {
  801.                     // Create styled text from 'styl' and 'TEXT' flavors
  802. #ifdef ODDebug_DragAndDrop
  803.                     somPrintf("GetPromiseFromDragManager: Creating 'stxt' from 'styl' and 'TEXT'\n");
  804. #endif
  805.                     destSUView->SetOffset(ev,0);
  806.                     result = CopyFromDragItemInChunks(ev, kODScrapTypestyl, theItem, _fDragReference, destSUView);
  807.                     destSUView->SetOffset(ev, destSUView->GetSize(ev));
  808.                     result = CopyFromDragItemInChunks(ev, kODScrapTypeTEXT, theItem, _fDragReference, destSUView);
  809.                 }
  810.                 else
  811.                 {        
  812.                     destSUView->SetOffset(ev,0);
  813.                     result = CopyFromDragItemInChunks(ev, platformType, theItem, _fDragReference, destSUView);
  814.                 }
  815.             }
  816.             ODDisposePtr(isoType);
  817.         
  818.         CATCH_ALL
  819.         
  820.             if (dataHandle)
  821.                 ODDisposeHandle(dataHandle);
  822.             if (isoType)
  823.                 ODDisposePtr(isoType);
  824.             RERAISE;
  825.         
  826.         ENDTRY
  827.     }
  828.     
  829.     SOM_CATCH_ALL
  830.     SOM_ENDTRY
  831. }
  832.  
  833. SOM_Scope void  SOMLINK ODDragAndDropGetDataFromDragManager(ODDragAndDrop *somSelf, Environment *ev,
  834.         ODStorageUnitView*    suView)
  835. {
  836.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  837.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDataFromDragManager");
  838.     
  839.     WARN("ODDragAndDropGetDataFromDragManager is obsoleted.\n");
  840. }
  841.  
  842.  
  843. SOM_Scope ODDragItemIterator*  SOMLINK 
  844. ODDragAndDropCreateDragItemIterator(ODDragAndDrop *somSelf, Environment *ev,
  845.         ODPlatformDragReference theDrag,
  846.         unsigned long startDragItemRef,
  847.         unsigned long endDragItemRef)
  848. {
  849.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  850.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemIterator");
  851.  
  852.     OSErr                returnCode = noErr; ODVolatile(returnCode);
  853.     OSErr                result = noErr;        ODVolatile(result);
  854.     ODDragLink*            newLink = kODNULL;    ODVolatile(newLink);
  855.     ODUShort            items = 0;            ODVolatile(items);
  856.     ODDragItemIterator* returnIter = kODNULL; ODVolatile(returnIter);
  857.     LinkedListIterator*    newIter    = kODNULL;    ODVolatile(newIter);
  858.     SOM_TRY
  859.             
  860.         CountDragItems(theDrag, &items);
  861.  
  862.         if( items < endDragItemRef || startDragItemRef > endDragItemRef )
  863.             THROW(kODErrDragItemNotFound);
  864.                      
  865.         for (ODUShort itemRefIndex = startDragItemRef; itemRefIndex <= endDragItemRef; ++itemRefIndex)
  866.         {    
  867.             ItemReference    itemID;
  868.             FlavorFlags        theFlags;
  869.             result = GetDragItemReferenceNumber(theDrag, itemRefIndex, &itemID);
  870.             result = GetFlavorFlags(theDrag, itemID, kODPromiseFlavor, &theFlags);
  871.             if (result == noErr)
  872.             {
  873.                 if (_fDragReference != theDrag)
  874.                 {    
  875.                     _fListFromHandler = kODTrue;
  876.                     newLink = new ODDragLink((ODDragItem*)itemID, kODFalse);
  877.                     _fDragItemList->AddLast((Link*)newLink);
  878.                 }
  879.             }
  880.             if (result == badDragFlavorErr)
  881.             {
  882.                 // Need to do this here because the drag wasn't inititiated by a part, so
  883.                 // no one has cleared the D&D SU yet.
  884.                 somSelf->Clear(ev);
  885.                 if( _fDragItemList == kODNULL )
  886.                     _fDragItemList = new LinkedList;
  887.         //            somSelf->SetDragItemList( ev, new LinkedList );
  888.                 
  889.                 ODStorageSystem*    storage = _fStorageSystem;
  890.                 ODTranslation*        translate = _fSession->GetTranslation(ev);
  891.                 ODDragItem*            newItem = kODNULL;        ODVolatile(newItem);
  892.                 
  893.                 ODUShort    count;            
  894.                 ODUShort    flavorIndex = 1;
  895.                 HFSFlavor*    hfsFlavor = (HFSFlavor*)ODNewPtr( sizeof(HFSFlavor) );
  896.                 CountDragItemFlavors(theDrag, itemID, &count);
  897.     
  898.                 // Do something special for: Bento files, Finder files, and data
  899.                 // interchange container types.
  900.                 for (flavorIndex = 1; (flavorIndex <= count) && (newItem == kODNULL); flavorIndex++)
  901.                 {   OSType    theType;
  902.                     OSErr    err         = GetFlavorType(theDrag, itemID, flavorIndex, &theType);
  903.                     if ((err == noErr) && (theType == flavorTypeHFS))
  904.                     {  
  905.                          Size  dataSize = sizeof(HFSFlavor);
  906.                         OSErr err = GetFlavorData(theDrag, itemID, theType, hfsFlavor,
  907.                                                   (Size*) &dataSize, 0);
  908.                         if (err == noErr)
  909.                         {    
  910.                             FSSpec* targetFileSpec = &(hfsFlavor->fileSpec);
  911.                             if (IsOpenDocDocument(hfsFlavor))
  912.                             {    
  913.                             // The item is a Bento file container; create the update container for it.
  914.                                 // Later we will put the HFS info in it, even if it is a read-only file.
  915.                                 ODBoolean wasAliased;
  916.                                 ODBoolean targetIsFolder;
  917.                                 OSErr err = ResolveAliasFile(targetFileSpec, TRUE, &targetIsFolder, &wasAliased);
  918.                                 if ((err == noErr)  && (!targetIsFolder)) {
  919.                                     FInfo    finderInfo;
  920.                                     err = FSpGetFInfo(targetFileSpec, &finderInfo);
  921.                                     if ((err == noErr) && IsOpenDocDocument(hfsFlavor /*finderInfo.fdType*/)) {
  922.                                         ODByteArray*    ba = CreateByteArray(targetFileSpec, sizeof(FSSpec));
  923.                                         TRY
  924.                                             newItem = new(ODGetDefaultHeap()) ODFileDragItem(storage, kODTrue,
  925.                                                                                 theDrag, itemID, hfsFlavor);
  926.                                             ((ODFileDragItem*) newItem)->Initialize(ev, ba);
  927.                                         CATCH_ALL
  928.                                             delete newItem;
  929.                                             newItem = kODNULL;
  930.                                         ENDTRY
  931.                                         DisposeByteArray(ba);
  932.                                     }
  933.                                 }
  934.                             }
  935.                             else if( IsOpenDocClipping( hfsFlavor ) )
  936.                             {
  937.                                 // The user has dragged in a clipping that has Bento container data.
  938.                                 // While we will get a drag flavor of type kODBentoFlavor that we could have
  939.                                 // loaded in a later section just like the data had come from the Scrapbook,
  940.                                 // the Finder won't resolve its promise for that data to the Drag Manager,
  941.                                 // so we can't use the Drag Manager API to load the data.
  942.                                 // Instead, we need to load the data directly from the clipping's resource fork.
  943.  
  944.                                 ODHandle tempHandle = kODNULL; ODVolatile( tempHandle );                                
  945.  
  946.                                 TRY
  947.                                     tempHandle = ReadOpenDocDataFromClippingFile( hfsFlavor );
  948.                                     if( tempHandle == kODNULL )
  949.                                         THROW( kODErrDragTrackingException );
  950.                                     ODLockHandle( tempHandle );
  951.                                     newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, tempHandle,
  952.                                                                                     kODTrue,theDrag, itemID, kODNULL);
  953.                                     ODUnlockHandle(tempHandle);
  954.                                 CATCH_ALL
  955.                                     if( newItem )
  956.                                         { ODDeleteObject( newItem ); }
  957.                                     else
  958.                                     { 
  959.                                         if( tempHandle != kODNULL )
  960.                                             ODDisposeHandle( tempHandle ); 
  961.                                     }
  962.                                     RERAISE;
  963.                                 ENDTRY
  964.  
  965.                             }
  966.                             else
  967.                             {    if( _fMemItemContainer == kODNULL)
  968.                                 {
  969.                                     ODHandle memContainerHandle = ODNewHandle(0);
  970.                                     _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  971.                                                 memContainerHandle, kODBentoMemoryContainer);
  972.                                     // _fMemItemContainer->Acquire(ev);    
  973.                                     ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );
  974.                                     _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  975.                                     // Refs to container/doc/draft will be released in Clear method.
  976.                                 }
  977.                                 newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, _fCachedMemContainerDraft,
  978.                                                                         kODTrue, theDrag, itemID, hfsFlavor);
  979.                                 ((ODMemDragItem*) newItem)->Initialize(ev);
  980.                             }
  981.                         }
  982.                     }
  983.                     if( theType == kODBentoFlavor )
  984.                     {
  985.                         // The item is a memory container handle that had been either:
  986.                         // a. Dragged to a non-OpenDoc process (like the Scrapbook) then dragged back.
  987.                         // b. Put on the Clipboard, pasted into non-OpenDoc process, then dragged back.
  988.                         // So, recreate the memory container.
  989.                     
  990.                         ODHandle tempHandle = kODNULL;
  991.                         ODVolatile( tempHandle );
  992.                         TRY
  993.                              Size flavorSize = 0;
  994.                              
  995.                             OSErr DragSizeErr = GetFlavorDataSize( theDrag, itemID, theType, &flavorSize );
  996.                             if( DragSizeErr != noErr )
  997.                                 THROW( DragSizeErr );
  998.                             tempHandle = ODNewHandle( flavorSize );
  999.                             ODLockHandle( tempHandle );
  1000.                             OSErr DragDataErr = GetFlavorData(theDrag, itemID, theType, *tempHandle, (Size*) &flavorSize, 0);
  1001.                             if( DragDataErr != noErr )
  1002.                                 THROW( DragDataErr );
  1003.                             ODUnlockHandle(tempHandle);
  1004.                             newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, tempHandle,
  1005.                                                                             kODTrue,theDrag, itemID, kODNULL);
  1006.                         CATCH_ALL
  1007.                             if( newItem )
  1008.                                 { ODDeleteObject( newItem ); }
  1009.                             else
  1010.                                 { ODDisposeHandle( tempHandle ); }
  1011.                             if( MemError() != noErr || ErrorCode() != cantGetFlavorErr )    // -1854 = cantGetFlavorErr
  1012.                             {
  1013.                                 RERAISE;                
  1014.                                 // We could get error cantGetFlavorErr because we are trying to load data from a
  1015.                                 // clipping, and the Finder will not resolve drag promises at DragTrack time.
  1016.                                 // Therefor, we will load OpenDoc data from clippings in the routine
  1017.                                 // above in the hfs secion, and do not need to Reraise this error.
  1018.                                 // But, we do want to reraise it when we get it because we are out of memory,
  1019.                                 // which means that there really was an error loading the flavor data or
  1020.                                 // getting its size.
  1021.                             }
  1022.                         ENDTRY
  1023.                     }
  1024.                 }
  1025.                 if (newItem == kODNULL)
  1026.                 {    // Otherwise, the item was neither a memory or file container.
  1027.                     // Just make a new drag item for it. We will use one container to
  1028.                     // hold all non-container data, and just create new storage units for
  1029.                     // each new item.
  1030.                     if( _fMemItemContainer == kODNULL ) {
  1031.                         ODHandle memContainerHandle = ODNewHandle(0);
  1032.                         _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  1033.                                                 memContainerHandle, kODBentoMemoryContainer);
  1034.                         // _fMemItemContainer->Acquire(ev);            
  1035.                         ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );
  1036.                         _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1037.                         // Refs to container/doc/draft will be released in Clear method.
  1038.                     }
  1039.                     newItem = new(ODGetDefaultHeap()) ODMemDragItem(storage, _fCachedMemContainerDraft, kODTrue, theDrag,
  1040.                                                                                 itemID, hfsFlavor);
  1041.                     ((ODMemDragItem*) newItem)->Initialize(ev);
  1042.                 }
  1043.                 _fListFromHandler = kODTrue;
  1044.                 newLink = new ODDragLink(newItem, kODTrue);
  1045.                 _fDragItemList->AddLast((Link*)newLink);
  1046.             }
  1047.             else
  1048.             {    WASSERTM(result == noErr, "Error from GetFlavorFlags in tracking handler");
  1049.                 returnCode = result;
  1050.                 break;
  1051.             }
  1052.         }
  1053.         
  1054.         _fDragReference = theDrag;
  1055.         _fAttributes = 0;
  1056.         if (_fListFromHandler)
  1057.         {    newIter = new LinkedListIterator(_fDragItemList);
  1058.             returnIter = new ODDragItemIterator();
  1059.             THROW_IF_NULL(returnIter, kODErrOutOfMemory);
  1060.             returnIter->InitDragItemIterator(ev, newIter);
  1061.             _fDragItemIterator = returnIter;
  1062.         }
  1063.     
  1064.     SOM_CATCH_ALL
  1065.         if (_fDragItemList)
  1066.         {
  1067.             // &&&&&
  1068.             _fDragItemList->DeleteAllLinks();
  1069.             delete _fDragItemList;
  1070.             _fDragItemList = kODNULL;
  1071.         }
  1072.         if( newIter )
  1073.             delete newIter;
  1074.         if( returnIter )
  1075.             delete returnIter;
  1076.         if( newLink )
  1077.             delete newLink;
  1078.     SOM_ENDTRY
  1079.  
  1080.     return returnIter;
  1081. }
  1082.  
  1083.  
  1084.  
  1085. SOM_Scope void  SOMLINK ODDragAndDropsomUninit(ODDragAndDrop *somSelf)
  1086. {
  1087.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1088.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropsomUninit");
  1089.  
  1090.     Environment* ev = somGetGlobalEnvironment();
  1091.     somSelf->Clear(ev);
  1092.         
  1093.     if (_fDragItemList)
  1094.     {
  1095. //        _fDragItemList->DeleteAllLinks();
  1096.         delete _fDragItemList;
  1097.     }
  1098. //    if (_fDragItemIterator)
  1099. //        delete _fDragItemIterator;
  1100.     if (_fReceiveHandler)
  1101.     {
  1102.         RemoveReceiveHandler(_fReceiveHandler, NULL);
  1103.         DisposeRoutineDescriptor(_fReceiveHandler);
  1104.     }
  1105.     if (_fTrackingHandler)
  1106.     {
  1107.         RemoveTrackingHandler(_fTrackingHandler, NULL);
  1108.         DisposeRoutineDescriptor(_fTrackingHandler);
  1109.     }
  1110.     if (_fSendDataHandler)
  1111.     {
  1112.         DisposeRoutineDescriptor(_fSendDataHandler);
  1113.     }
  1114.     
  1115.     ODDeleteObject(_fFacetsRejected);
  1116.     
  1117.     ODDisposePtr(_fPSN);
  1118.     ODDisposePtr(_fReplaceFileEvent);
  1119. }
  1120.  
  1121. SOM_Scope void  SOMLINK ODDragAndDropClear(ODDragAndDrop *somSelf, Environment *ev)
  1122. {
  1123.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1124.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropClear");
  1125.  
  1126. #if ODDebug_DragAndDrop
  1127.     somPrintf("In Clear\n");
  1128. #endif
  1129.  
  1130.     SOM_TRY
  1131.         // Need this here because we don't want to cause a fatal Bento error clearing
  1132.         // the D&D container under low-mem, since this would kill our process.
  1133.         TempSuppressFatalBentoError wereSupressing;
  1134.     
  1135.         if (_fTrackingHandler == kODNULL)
  1136.             ODSetSOMException(ev, kODErrNoDragManager);
  1137.         else
  1138.         {
  1139.             if (_fDragItemIterator)
  1140.             {
  1141.                 delete _fDragItemIterator;
  1142.                 _fDragItemIterator = kODNULL;
  1143.             }
  1144.             _fDragItemList->DeleteAllLinks();
  1145.         }
  1146.  
  1147.         int refCnt = 0;
  1148.         if( _fMemItemContainer != kODNULL )
  1149.         {
  1150.             // Release temp in-memory container holding SU's for non-Bento files dragged in:
  1151.             ODByteArray ba = _fMemItemContainer->GetID(ev);    // Get storage handle from container ID.
  1152.             WASSERT(ba._length==sizeof(ODHandle));
  1153.             
  1154.             if( _fCachedMemContainerDraft != kODNULL )
  1155.             {
  1156.                 ODSafeReleaseObject( _fCachedMemContainerDraft );    // Undoes Acquire in EnterHandler.
  1157.                 _fCachedMemContainerDraft = kODNULL;
  1158.             }
  1159.             
  1160.             ODDocument* doc = _fMemItemContainer->AcquireDocument(ev, kODDefaultDocument);
  1161.             if( doc != kODNULL )
  1162.             {
  1163.                 WASSERT(( refCnt = doc->GetRefCount(ev) )==2);
  1164.                 ODSafeReleaseObject( doc );     // Undoes our Acquire above.
  1165.                 ODSafeReleaseObject( doc );        // Undoes Acquire in EnterHandler.
  1166.             }
  1167.             WASSERT( (refCnt = _fMemItemContainer->GetRefCount(ev) )==1);
  1168.             ODSafeReleaseObject(_fMemItemContainer);
  1169.             _fMemItemContainer = kODNULL;
  1170.  
  1171.             ODDisposeHandle( *(ODHandle*)ba._buffer);        // Finally dispose storage handle.
  1172.             delete ba._buffer;
  1173.             
  1174.         }
  1175.     SOM_CATCH_ALL
  1176.         // The clear method is a notification that parts are required to call as part of the drag and drop
  1177.         // protocal. Parts are not concerned with what this method does, or even if it succeeds. Calling this
  1178.         // method is its sole responsibility for the protocal, and does not have to respond to any problems.
  1179.         // Therefor, don't propogate any exceptions to the part. 
  1180.         ODSetSOMException(ev, kODNoError);
  1181.     SOM_ENDTRY
  1182.  
  1183. }
  1184.  
  1185. SOM_Scope ODStorageUnit*  SOMLINK ODDragAndDropGetContentStorageUnit(ODDragAndDrop *somSelf, Environment *ev)
  1186. {
  1187.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1188.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetContentStorageUnit");
  1189.  
  1190.     ODStorageUnit* contentSU = kODNULL;
  1191.     
  1192.     if (_fTrackingHandler == kODNULL)
  1193.         ODSetSOMException(ev, kODErrNoDragManager);
  1194.     else {
  1195.         SOM_TRY
  1196.  
  1197.             ODMemDragItem    *newItem;
  1198.             ODDragLink        *newLink;
  1199.         
  1200.             if( _fMemItemContainer == kODNULL ) {
  1201.                 ODHandle memContainerHandle = ODNewHandle(0);
  1202.                 _fMemItemContainer = CreateMemoryContainer(ev, _fSession,
  1203.                                         memContainerHandle, kODBentoMemoryContainer);
  1204. //                _fMemItemContainer->Acquire(ev);
  1205.                 ODDocument* theDocument = _fMemItemContainer->AcquireDocument( ev, kODDefaultDocument );    
  1206.                 _fCachedMemContainerDraft = theDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  1207.                 // Refs to container/doc/draft will be released in Clear method.
  1208.             }
  1209.             newItem = new(ODGetDefaultHeap()) ODMemDragItem(_fStorageSystem, _fCachedMemContainerDraft, kODFalse, 0, 0, kODNULL);
  1210.             ASSERTM(newItem != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag item");
  1211.             newItem->Initialize(ev);
  1212.             newLink = new ODDragLink(newItem, kODTrue);
  1213.             if (!newLink)
  1214.             {
  1215.                 delete newItem;
  1216.                 ASSERTM(newLink != kODNULL, kODErrCannotAllocateDragItem, "Error allocating drag link");
  1217.             }
  1218.             _fDragItemList->AddLast(newLink);
  1219.             contentSU = newItem->GetStorageUnit(ev);
  1220.             
  1221.         SOM_CATCH_ALL
  1222.         SOM_ENDTRY
  1223.     }
  1224.     return contentSU;
  1225. }
  1226.  
  1227. SOM_Scope ODDropResult  SOMLINK ODDragAndDropStartDrag(ODDragAndDrop *somSelf, Environment *ev,
  1228.         ODFrame* srcFrame,
  1229.         ODType imageType,
  1230.         ODByteArray* image,
  1231.         ODPart** destPart,
  1232.         ODByteArray* refCon)
  1233. {
  1234.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1235.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropStartDrag");
  1236.  
  1237.     LinkedListIterator *theIter = kODNULL;    ODVolatile(theIter);
  1238.  
  1239. SOM_TRY
  1240.     if (_fTrackingHandler == kODNULL)
  1241.         THROW(kODErrNoDragManager);
  1242.  
  1243.     ASSERT(image != kODNULL, kODErrIllegalNullInput);
  1244.     ASSERT(refCon != kODNULL, kODErrIllegalNullInput);
  1245.  
  1246.     OSErr               result;
  1247.     RgnHandle           imageRgn;
  1248.     ODTranslation     *translate;
  1249.     ODULong            count, index;
  1250.     ODType             theISOType;
  1251.     ODPlatformType     platformType;
  1252.     PromiseHFSFlavor    thePromise;
  1253.     ODStorageUnit     *theSU;
  1254.     ODDragLink        *theDragLink;
  1255.  
  1256.     // Check if we know what the image type is
  1257.     ASSERTM(ODISOStrEqual(imageType, kODDragImageRegionHandle), kODErrUnknownDragImageType, "Unknown image type in StartDrag");
  1258.  
  1259.     // Set the drop result to kODDropFail. - VL
  1260.     _fDropResult = kODDropFail;
  1261.     
  1262.     // Begin the drag by creating a new drag reference
  1263.     result = NewDrag(&_fDragReference);
  1264.     ASSERTM(result == noErr, result, "Bad result from NewDrag");
  1265.     
  1266. #ifdef ODDebug_DragAndDrop
  1267. //    PrintDragReference(_fDragReference, "After NewDrag");
  1268. #endif
  1269.  
  1270.     // Register a send procedure so we don't have to cache any data with the drag manager
  1271.     result = SetDragSendProc(_fDragReference, _fSendDataHandler, (void *) somSelf);
  1272.     ASSERTM(result == noErr, result, "Bad result from SetDragSendProc");
  1273.  
  1274.     // Scan through all items in the drag and add a flavor for each value
  1275.     // in the storage unit's kODContents property
  1276.     theIter = new LinkedListIterator(_fDragItemList);
  1277.     translate = _fSession->GetTranslation(ev);
  1278.     imageRgn = *((RgnHandle*) image->_buffer);
  1279.     for (theDragLink = (ODDragLink*)theIter->First(); theDragLink; theDragLink = (ODDragLink*)theIter->Next())
  1280.     {
  1281.         theSU = theDragLink->fItem->GetStorageUnit(ev);
  1282.         ODBoolean    userPromise = ODSUExistsThenFocus(ev, theSU, kODPropContents, kODHFSPromise);
  1283.         if (userPromise)
  1284.         {
  1285.             ODByteArray ba;
  1286.             ODPart* dummySourcePart;
  1287.             theSU->GetPromiseValue(ev, kODHFSPromise, 0, sizeof(PromiseHFSFlavor), &ba, &dummySourcePart);
  1288.             if (ba._buffer)
  1289.             {
  1290.                 ODBlockMove(ba._buffer, &thePromise, ba._length);
  1291.                 ODDisposePtr(ba._buffer);
  1292.             }
  1293.             thePromise.promisedFlavor = kODUserPromiseFlavor;
  1294.         }
  1295.         else
  1296.         {
  1297.             // Always promise a file in case somebody wishes to drag this out to the finder
  1298.             thePromise.fileType = GetStorageUnitOSType(ev,theSU);
  1299.             thePromise.fileCreator = ODGetIconFilePlatformCreatorFromPartSU(ev,theSU);
  1300.             thePromise.fdFlags = 0;
  1301.             thePromise.promisedFlavor = kODBentoFlavor;
  1302.         }
  1303.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), flavorTypePromiseHFS,
  1304.                                    &thePromise, sizeof(PromiseHFSFlavor), 0);
  1305.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1306.  
  1307.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), (userPromise ? kODUserPromiseFlavor : kODBentoFlavor), 0L, 0L, 0);
  1308.         ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1309.         
  1310.         result = SetDragItemBounds(_fDragReference, (ItemReference)(theDragLink->fItem), &((**imageRgn).rgnBBox));
  1311.         ASSERTM(result == noErr, result, "Bad result from SetDragItemBounds");
  1312.  
  1313. #ifdef ODDebug_DragAndDrop
  1314. //    PrintStorageUnit(ev, theSU, "DragItem SU");
  1315. #endif
  1316.         theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
  1317.         count = theSU->CountValues(ev);
  1318.         for (index = 1; index <= count; ++index)
  1319.         {
  1320.             theSU->Focus(ev,kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
  1321.             theISOType = theSU->GetType(ev);
  1322.             platformType = translate->GetPlatformTypeFromISOType(ev, theISOType);
  1323.             ODDisposePtr(theISOType);
  1324.             if (!platformType)
  1325.                 continue;
  1326.             result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), platformType, 0L, 0L, 0);
  1327.             ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1328.  
  1329.             // If styled text ('stxt') was just added, also add 'styl' if
  1330.             // a 'TEXT' representation will also be written.
  1331.             if (     (platformType == kODScrapTypestxt)
  1332.                   && theSU->Exists(ev, kODPropContents, kODAppleTEXT, 0)
  1333.                   && !theSU->Exists(ev, kODPropContents, kODApplestyl, 0) )
  1334.             {
  1335.                 result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODScrapTypestyl, 0L, 0L, 0);
  1336.                 ASSERTM(result == noErr, result, "Bad result from AddDragItemFlavor");
  1337.             }
  1338.         }
  1339.     
  1340.         // Always add our special dummy promise to the drag
  1341.         result = AddDragItemFlavor(_fDragReference, (ItemReference)(theDragLink->fItem), kODPromiseFlavor, 0L, 0L, 0);
  1342.         ASSERTM(result == noErr, result, "Bad result from adding kODPromiseFlavor");
  1343.     }
  1344.  
  1345.     _fSourceFrame = srcFrame;
  1346.     _fSourcePart = srcFrame->AcquirePart(ev);
  1347.  
  1348.     TRY
  1349.         TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1350.         
  1351.         _fDestFacet = kODNULL;
  1352.         _fDragItemIterator = new ODDragItemIterator();
  1353.         THROW_IF_NULL(_fDragItemIterator, kODErrOutOfMemory);
  1354.         _fDragItemIterator->InitDragItemIterator(ev, theIter);
  1355.         _fHasLeftSourceFrame = kODFalse;
  1356.         _fHasLeftSourcePart = kODFalse;
  1357.         
  1358.         #ifdef ODDebug_DragAndDrop
  1359.         //    PrintDragReference(_fDragReference, "Before TrackDrag");
  1360.         #endif
  1361.     
  1362.         // Do the drag    
  1363.         result = TrackDrag(_fDragReference, *((EventRecord**) refCon->_buffer), imageRgn);
  1364.  
  1365.         if( result != noErr )
  1366.             THROW( result );
  1367.         if (_fDestFacet)
  1368.             *destPart = _fDestFacet->GetFrame(ev)->AcquirePart(ev);
  1369.         else
  1370.             *destPart = kODNULL;
  1371.     CATCH_ALL
  1372.         DisposeDrag(_fDragReference);
  1373.         _fDragReference = kODNULL;
  1374.         ODSafeReleaseObject( _fSourcePart);
  1375.         _fSourcePart = kODNULL;
  1376.         RERAISE;
  1377.     ENDTRY
  1378.             
  1379.     DisposeDrag(_fDragReference);
  1380.     _fDragReference = kODNULL;
  1381. //    if( _fDragItemIterator != kODNULL )
  1382. //    {
  1383. //        delete _fDragItemIterator;
  1384. //        _fDragItemIterator = kODNULL;
  1385. //    }    
  1386.  
  1387.     _fSourceFrame = kODNULL;
  1388.     ODSafeReleaseObject( _fSourcePart );
  1389.     _fSourcePart = kODNULL;
  1390.     _fDestFacet = kODNULL;
  1391. // dh - this shouldn't be needed. Parts should call Clear as part of the D&D protocol.
  1392.     somSelf->Clear(ev);
  1393.  
  1394.     if (_fShouldSendReplaceFileEvent)
  1395.     {
  1396.         _fShouldSendReplaceFileEvent = kODFalse;
  1397.         OSErr err = SetupReplaceFileEvent(ev,
  1398.             _fReplaceFileEvent,
  1399.             &gTmpFileFSSpec,
  1400.             &gTargetFSSpec);
  1401.         SendReplaceFileEvent(_fReplaceFileEvent, _fPSN);
  1402.         DisposeReplaceFileEvent(_fReplaceFileEvent);
  1403.         CreateReplaceFileEvent(ev,
  1404.             _fReplaceFileEvent,
  1405.             _fSession,
  1406.             _fPSN);
  1407.     }
  1408.  
  1409. SOM_CATCH_ALL
  1410.  
  1411.     if( _fDragItemIterator != kODNULL )
  1412.     {
  1413.         delete _fDragItemIterator;
  1414.         _fDragItemIterator = kODNULL;
  1415.     }    
  1416. // dh - this shouldn't be needed. Parts should call Clear as part of the D&D protocol.
  1417.     somSelf->Clear(ev);
  1418.     if (_fDragReference)
  1419.         DisposeDrag(_fDragReference);
  1420.     _fDragReference = kODNULL;
  1421.     
  1422. SOM_ENDTRY
  1423.  
  1424.     if (_fDropResult == kODDropMove)
  1425.         return kODDropMove;
  1426.     else if (_fDropResult == kODDropCopy)
  1427.         return kODDropCopy;
  1428.     else
  1429.         return kODDropFail;
  1430. }
  1431.  
  1432.  
  1433. SOM_Scope LinkedList*  SOMLINK ODDragAndDropGetDragItemList(ODDragAndDrop *somSelf, Environment *ev)
  1434. {
  1435.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1436.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemList");
  1437.  
  1438.     return _fDragItemList;
  1439. }
  1440.  
  1441. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemList(ODDragAndDrop *somSelf, Environment *ev,
  1442.         LinkedList* list)
  1443. {
  1444.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1445.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemList");
  1446.  
  1447.     _fDragItemList = list;
  1448. }
  1449.  
  1450. SOM_Scope ODBoolean  SOMLINK ODDragAndDropGetListFromHandler(ODDragAndDrop *somSelf, Environment *ev)
  1451. {
  1452.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1453.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetListFromHandler");
  1454.  
  1455.     return _fListFromHandler;
  1456. }
  1457.  
  1458. SOM_Scope void  SOMLINK ODDragAndDropSetListFromHandler(ODDragAndDrop *somSelf, Environment *ev,
  1459.         ODBoolean listFromHandler)
  1460. {
  1461.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1462.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetListFromHandler");
  1463.  
  1464.     _fListFromHandler = listFromHandler;
  1465. }
  1466.  
  1467. SOM_Scope ODFrame*  SOMLINK ODDragAndDropGetSourceFrame(ODDragAndDrop *somSelf, Environment *ev)
  1468. {
  1469.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1470.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourceFrame");
  1471.  
  1472.     return _fSourceFrame;
  1473. }
  1474.  
  1475. SOM_Scope void  SOMLINK ODDragAndDropSetSourceFrame(ODDragAndDrop *somSelf, Environment *ev,
  1476.         ODFrame* sourceFrame)
  1477. {
  1478.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1479.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourceFrame");
  1480.  
  1481.     _fSourceFrame = sourceFrame;
  1482. }
  1483.  
  1484. SOM_Scope ODULong  SOMLINK ODDragAndDropGetAttributes(ODDragAndDrop *somSelf, Environment *ev)
  1485. {
  1486.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1487.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetAttributes");
  1488.  
  1489.     return _fAttributes;
  1490. }
  1491.  
  1492. SOM_Scope void  SOMLINK ODDragAndDropSetAttributes(ODDragAndDrop *somSelf, Environment *ev,
  1493.         ODULong attr)
  1494. {
  1495.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1496.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetAttributes");
  1497.  
  1498.     _fAttributes = attr;
  1499. }
  1500.  
  1501. SOM_Scope ODPart*  SOMLINK ODDragAndDropGetSourcePart(ODDragAndDrop *somSelf, Environment *ev)
  1502. {
  1503.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1504.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSourcePart");
  1505.  
  1506.     return _fSourcePart;
  1507. }
  1508.  
  1509. SOM_Scope void  SOMLINK ODDragAndDropSetSourcePart(ODDragAndDrop *somSelf, Environment *ev,
  1510.         ODPart* sourcePart)
  1511. {
  1512.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1513.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetSourcePart");
  1514.  
  1515.     _fSourcePart = sourcePart;
  1516. }
  1517.  
  1518. SOM_Scope ODDragItemIterator*  SOMLINK ODDragAndDropGetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev)
  1519. {
  1520.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1521.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDragItemIterator");
  1522.  
  1523.     return _fDragItemIterator;
  1524. }
  1525.  
  1526. SOM_Scope void  SOMLINK ODDragAndDropSetDragItemIterator(ODDragAndDrop *somSelf, Environment *ev,
  1527.         ODDragItemIterator* iter)
  1528. {
  1529.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1530.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragItemIterator");
  1531.  
  1532.     _fDragItemIterator = iter;
  1533. }
  1534.  
  1535. SOM_Scope ODSession*  SOMLINK ODDragAndDropGetSession(ODDragAndDrop *somSelf, Environment *ev)
  1536. {
  1537.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1538.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetSession");
  1539.  
  1540.     return _fSession;
  1541. }
  1542.  
  1543. SOM_Scope ODStorageSystem*  SOMLINK ODDragAndDropGetStorageSystem(ODDragAndDrop *somSelf, Environment *ev)
  1544. {
  1545.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1546.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetStorageSystem");
  1547.  
  1548.     return _fStorageSystem;
  1549. }
  1550.  
  1551. SOM_Scope void  SOMLINK ODDragAndDropSetDragReference(ODDragAndDrop *somSelf, Environment *ev,
  1552.         ODPlatformDragReference dragReference)
  1553. {
  1554.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1555.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDragReference");
  1556.     
  1557.     _fDragReference = dragReference;
  1558. }
  1559.  
  1560. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetPrevFacet(ODDragAndDrop *somSelf, Environment *ev)
  1561. {
  1562.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1563.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetPrevFacet");
  1564.  
  1565.     return _fPrevFacet;
  1566. }
  1567.  
  1568. SOM_Scope void  SOMLINK ODDragAndDropSetPrevFacet(ODDragAndDrop *somSelf, Environment *ev,
  1569.         ODFacet* prevFacet)
  1570. {
  1571.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1572.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetPrevFacet");
  1573.  
  1574.     _fPrevFacet = prevFacet;
  1575. }
  1576.  
  1577. SOM_Scope ODFacet*  SOMLINK ODDragAndDropGetDestFacet(ODDragAndDrop *somSelf, Environment *ev)
  1578. {
  1579.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1580.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDestFacet");
  1581.  
  1582.     return _fDestFacet;
  1583. }
  1584.  
  1585. SOM_Scope void  SOMLINK ODDragAndDropSetDestFacet(ODDragAndDrop *somSelf, Environment *ev,
  1586.         ODFacet* destFacet)
  1587. {
  1588.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1589.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDestFacet");
  1590.  
  1591.     _fDestFacet = destFacet;
  1592. }
  1593.  
  1594. SOM_Scope ODDropResult  SOMLINK ODDragAndDropGetDropResult(ODDragAndDrop *somSelf, Environment *ev)
  1595. {
  1596.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1597.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1598.  
  1599.     return _fDropResult;
  1600. }
  1601.  
  1602. SOM_Scope void  SOMLINK ODDragAndDropSetDropResult(ODDragAndDrop *somSelf, Environment *ev,
  1603.         ODDropResult dropResult)
  1604. {
  1605.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1606.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropSetDropResult");
  1607.  
  1608.     _fDropResult = dropResult;
  1609. }
  1610.  
  1611. SOM_Scope ProcessSerialNumber*   SOMLINK ODDragAndDropGetPSN(ODDragAndDrop *somSelf, Environment *ev)
  1612. {
  1613.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1614.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1615.  
  1616.     return _fPSN;
  1617. }
  1618.  
  1619. SOM_Scope AppleEvent*   SOMLINK ODDragAndDropGetReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev)
  1620. {
  1621.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1622.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1623.  
  1624.     return _fReplaceFileEvent;
  1625. }
  1626.  
  1627. SOM_Scope void   SOMLINK ODDragAndDropSetShouldSendReplaceFileEvent(ODDragAndDrop *somSelf, Environment *ev,
  1628.     ODBoolean shouldSend)
  1629. {
  1630.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  1631.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropGetDropResult");
  1632.  
  1633.     _fShouldSendReplaceFileEvent = shouldSend;
  1634. }
  1635.  
  1636. pascal OSErr MyDragTrackingHandler(
  1637.         short message,
  1638.         WindowPtr theWindow,
  1639.         void* handlerRefCon,
  1640.         ODPlatformDragReference theDrag)
  1641. {
  1642.     ODDragAndDrop  *self = (ODDragAndDrop*)handlerRefCon;
  1643.     ODPoint            mouse, localMouse;
  1644.     OSErr            returnCode = noErr;
  1645.  
  1646.     TRY
  1647.         TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1648.     
  1649.         Environment*    ev = somGetGlobalEnvironment();
  1650.     
  1651.         switch (message)
  1652.         {
  1653.             case dragTrackingEnterHandler:
  1654.                 returnCode = self->EnterHandler(ev, theDrag);
  1655.                 break;            
  1656.             case dragTrackingEnterWindow:
  1657.                 returnCode = self->EnterWindow(ev, theDrag, theWindow);
  1658.                 break;
  1659.  
  1660.             case dragTrackingInWindow:
  1661.                 returnCode = self->InWindow(ev, theDrag, theWindow);
  1662.                 break;
  1663.                 
  1664.             case dragTrackingLeaveWindow:
  1665.                 returnCode = self->LeaveWindow(ev, theDrag, theWindow);
  1666.                 break;
  1667.                 
  1668.             case dragTrackingLeaveHandler:
  1669.                 returnCode = self->LeaveHandler(ev);
  1670.                 break;
  1671.         }
  1672.     
  1673.     CATCH_ALL
  1674.     
  1675.         returnCode = ErrorCode();
  1676.     
  1677.     ENDTRY
  1678.  
  1679.     return returnCode;
  1680. }
  1681.  
  1682. pascal OSErr    MyReceiveDropHandler(
  1683.         WindowPtr theWindow,
  1684.         void* handlerRefCon,
  1685.         ODPlatformDragReference theDrag)
  1686. {
  1687.     ODDragAndDrop    *self = (ODDragAndDrop*)handlerRefCon;
  1688.     ODPoint            mouse, localMouse;
  1689.     Point            qdMouse;
  1690.     ODFacet            *targetFacet;
  1691.     OSErr            returnCode = noErr;
  1692.  
  1693. #ifdef ODDebug_DragAndDrop
  1694.     somPrintf("MyReceiveDropHandler\n");
  1695. #endif
  1696.  
  1697.     Environment* ev = somGetGlobalEnvironment();
  1698.  
  1699.     TRY
  1700.     TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1701.  
  1702.     GetDragMouse(theDrag, &qdMouse, 0L);
  1703.     mouse = qdMouse;
  1704.     targetFacet = self->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  1705.         
  1706.     if (!targetFacet || !(self->GetDragItemList(ev)->Count()))
  1707.         returnCode = dragNotAcceptedErr;
  1708.     else
  1709.     {
  1710.         TempODPart targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  1711.  
  1712.         // Assume _fDropResult is kODDropMove
  1713.         
  1714.         self->SetDropResult(ev, kODDropMove);
  1715.         
  1716.         // Are we going across Drafts?
  1717.         
  1718.         ODPart* sourcePart = self->GetSourcePart(ev);
  1719.         if ((sourcePart == kODNULL) || 
  1720.             (targetPart->GetStorageUnit(ev)->GetDraft(ev) != 
  1721.             sourcePart->GetStorageUnit(ev)->GetDraft(ev)))
  1722.             self->SetDropResult(ev, kODDropCopy);
  1723.  
  1724.         ODSShort    mouseDownModifiers;
  1725.         ODSShort    mouseUpModifiers;
  1726.                 
  1727.         GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1728.  
  1729.         // Check the mandatory modifier keys first
  1730.         
  1731.         if (mouseUpModifiers & optionKey) {
  1732.             self->SetDropResult(ev, kODDropCopy);
  1733.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1734.         }
  1735.         else if (mouseUpModifiers & controlKey) {
  1736.             self->SetDropResult(ev, kODDropMove);
  1737.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1738.         }
  1739.         else if (mouseUpModifiers & cmdKey) {
  1740.             SetPasteAsAttribute(self, ev, mouseUpModifiers);
  1741.         }
  1742.  
  1743.         // Then check the optional modifier keys
  1744.         
  1745.         else if (mouseDownModifiers & optionKey) {
  1746.             self->SetDropResult(ev, kODDropCopy);
  1747.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1748.         }
  1749.         else if (mouseDownModifiers & controlKey) {
  1750.             self->SetDropResult(ev, kODDropMove);
  1751.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1752.         }
  1753.         else if (mouseDownModifiers & cmdKey) {
  1754.             SetPasteAsAttribute(self, ev, mouseDownModifiers);
  1755.         }
  1756.                     
  1757.         // Check to see whether it is an override by source part.
  1758.         ODDragItemIterator* dragItemIter = self->GetDragItemIterator(ev);
  1759.         if (dragItemIter)
  1760.         {
  1761.             ODStorageUnit* su = dragItemIter->First(ev);
  1762.             ODDraft* draft = su->GetDraft(ev);
  1763.             ODCloneKind cloneKind = GetOriginalCloneKind(ev, draft);
  1764.             if (cloneKind == kODCloneCopy)
  1765.                 self->SetDropResult(ev, kODDropCopy);
  1766.         }
  1767.         
  1768.         // Drop
  1769. #ifdef ODDebug_DragAndDrop
  1770.     somPrintf("Calling Drop on targetFacet %x\n", targetFacet);
  1771. #endif
  1772.  
  1773.         self->SetAttributes(ev, self->GetAttributes(ev) | 
  1774.                 (self->GetDropResult(ev) == kODDropMove ? kODDropIsMove : kODDropIsCopy));
  1775.                 
  1776.         if (targetFacet->GetFrame(ev) == self->GetSourceFrame(ev))
  1777.             self->SetAttributes(ev, self->GetAttributes(ev) | (kODDropIsInSourceFrame | kODDropIsInSourcePart));
  1778.         else if (targetPart == self->GetSourcePart(ev))
  1779.             self->SetAttributes(ev, self->GetAttributes(ev) | kODDropIsInSourcePart);
  1780.                 
  1781.         self->SetDestFacet(ev, targetFacet);
  1782.         self->SetPrevFacet(ev, kODNULL);
  1783.         ODULong dropResult; ODVolatile(dropResult);
  1784.         SOM_TRY
  1785.              dropResult= targetFacet->Drop(ev, &localMouse, self->GetDragItemIterator(ev), kODNULL);
  1786.         SOM_CATCH_ALL
  1787.         SOM_ENDTRY
  1788.         if (dropResult == kODDropFail) {
  1789.             self->SetDropResult(ev, dropResult);
  1790.             returnCode = dragNotAcceptedErr;
  1791. //            returnCode = ErrorCode();
  1792.         }
  1793.         else if ((self->GetDropResult(ev) == kODDropMove) && (dropResult == kODDropCopy)) {
  1794.             self->SetDropResult(ev, kODDropCopy);
  1795.             returnCode = noErr;
  1796.         }
  1797.         
  1798.         ODDragItemIterator* iter = self->GetDragItemIterator(ev);
  1799.         ODSession* destSession = self->GetSession(ev);
  1800.         for (ODStorageUnit* su = iter->First(ev); iter->IsNotComplete(ev); su = iter->Next(ev)) {
  1801.             ODSession* sourceSession = su->GetSession(ev);
  1802.             if ((sourceSession != kODNULL) && (sourceSession != destSession)) {
  1803.                 ODDragAndDrop* sourceDAD = sourceSession->GetDragAndDrop(ev);
  1804.                 if (sourceDAD != kODNULL) {
  1805.                     sourceDAD->SetDropResult(ev, self->GetDropResult(ev));
  1806.                     sourceDAD->SetDestFacet(ev, targetFacet);
  1807.                 }
  1808.             }
  1809.         }
  1810.     }
  1811.  
  1812.     CATCH_ALL
  1813.  
  1814.     self->SetDropResult(ev, kODDropFail);
  1815.     returnCode = dragNotAcceptedErr;
  1816. #if ODDebug            
  1817.     somPrintf("Error in MyReceiveDropHandler.\n");
  1818. #endif
  1819.  
  1820.     ENDTRY
  1821.  
  1822.     ODEventData    event;
  1823.     WaitNextEvent(mUpMask, (EventRecord*) &event, 0, kODNULL);
  1824. #if ODDebug_DragAndDrop            
  1825.     somPrintf("message %x when %x where %x modifier %x\n", event.message, event.when, event.where, event.modifiers);
  1826. #endif
  1827.  
  1828.     return returnCode;
  1829. }
  1830.  
  1831. pascal OSErr  MySendDataProc(
  1832.         FlavorType theType,
  1833.         void* refCon,
  1834.         ItemReference theItem,
  1835.         ODPlatformDragReference theDrag)
  1836. {
  1837.     ODDragAndDrop    *self = (ODDragAndDrop*)refCon;
  1838.     Environment*    ev = somGetGlobalEnvironment();
  1839.     OSErr            result = noErr;
  1840.     ODType            theISOType;
  1841.     ODTranslation    *translate;
  1842.     AEDesc            dropDescriptor;
  1843.     ODPtr            stylPtr = kODNULL;
  1844.     ODULong            stylSize = 0;
  1845.  
  1846.     ODVolatile(result);
  1847.     TRY
  1848.     
  1849.     TempDelayBentoFatalError tempDelay; // delay in drag&drop
  1850.  
  1851.     LinkedListIterator iter(self->GetDragItemList(ev));
  1852.     ODDragLink*        theDragLink = kODNULL;
  1853.     ODMemDragItem*    theDragItem = kODNULL;
  1854.  
  1855. #ifdef ODDebug_DragAndDrop
  1856.     somPrintf("Entering MySendDataProc.\n");
  1857. #endif
  1858.  
  1859.     for (theDragLink = (ODDragLink*)iter.First(); 
  1860.          theDragLink; theDragLink = (ODDragLink*)iter.Next())
  1861.     {
  1862.         if (theDragLink->fItem == (ODDragItem*)theItem)
  1863.         {
  1864.             theDragItem = (ODMemDragItem*) theDragLink->fItem;
  1865.             break;
  1866.         }
  1867.     }
  1868.     if (!theDragItem)
  1869.     {
  1870.         WARN("Item not found in send proc");
  1871.         result =  badDragFlavorErr;
  1872.     }
  1873.     else {
  1874.         switch (theType)
  1875.         {
  1876.             case kODPromiseFlavor:
  1877. #ifdef ODDebug_DragAndDrop
  1878.     somPrintf("MySendDataProc: kODPromiseFlavor\n");
  1879. #endif
  1880.                 if (gIsResolvingPromise)
  1881.                 {
  1882.                     result = GetDropLocation(theDrag, &dropDescriptor);
  1883.                     if ((result != noErr) || (dropDescriptor.descriptorType != kODPromiseDesc)) {
  1884.                         WARN("Error from GetDropLocation in send procedure");
  1885.                     }
  1886.                     else {
  1887.                         ODPromiseDesc     theInfo;
  1888.                         ODBlockMove((Ptr)(*dropDescriptor.dataHandle), (Ptr)&theInfo, sizeof(ODPromiseDesc));
  1889.                         if (theInfo.sourcePart && theInfo.destSUView)
  1890.                         {
  1891.                             TRY
  1892.                                 theInfo.sourcePart->FulfillPromise(ev, theInfo.destSUView);
  1893.                             CATCH_ALL
  1894.                                 WARN("Error from FulfillPromise.");
  1895.                             ENDTRY
  1896.                         }
  1897.                     result = noErr;
  1898.                     }
  1899.                 }
  1900.             break;
  1901.             case kODUserPromiseFlavor:
  1902. #ifdef ODDebug_DragAndDrop
  1903.     somPrintf("MySendDataProc: kODUserPromiseFlavor\n");
  1904. #endif
  1905.                 result = noErr;
  1906.                 ODStorageUnit* contentSU = theDragItem->GetStorageUnit(ev);
  1907.                 if ((contentSU != kODNULL) && (contentSU->Exists(ev, kODPropContents, kODHFSPromise, 0)))
  1908.                 {
  1909.                     FSSpec dropFSSpec;
  1910.                     result = GetDropFSSpec(theDrag, dropFSSpec);
  1911.                     if (result == noErr)
  1912.                     {
  1913.                         TRY
  1914.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1915.                             StorageUnitSetPromiseValue(contentSU, ev, kODHFSPromise, 0, sizeof(FSSpec), &dropFSSpec, self->GetSourcePart(ev));
  1916.                             contentSU->Focus(ev, kODPropContents, kODPosUndefined, kODHFSPromise, 0, kODPosUndefined);
  1917.                             ODULong size = StorageUnitGetValue(contentSU, ev, sizeof(FSSpec), &dropFSSpec);
  1918.                             if (size != sizeof(FSSpec))
  1919.                             {
  1920.                                 self->SetDropResult(ev, kODDropFail);
  1921.                                 result = fnfErr;
  1922.                             }
  1923.                             else
  1924.                             {
  1925.                                 self->SetDropResult(ev, IsTrashFolder(dropFSSpec) ? kODDropMove : kODDropCopy);
  1926.                                 SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  1927.                             }
  1928.                         CATCH_ALL
  1929.                             WARN("Error from FulfillPromise.");
  1930.                         ENDTRY
  1931.                     }
  1932.                     // If we get a file not found error, most likely we are trying to drag to somewhere other than the Finder.
  1933.                     // That's OK, so just eat the error.
  1934.                     if( result == fnfErr )
  1935.                         result = noErr;
  1936.                 }
  1937.             break;
  1938.             case kODBentoFlavor:
  1939.             {
  1940. #ifdef ODDebug_DragAndDrop
  1941.     somPrintf("MySendDataProc: kODBentoFlavor\n");
  1942. #endif
  1943.                 // Check the drop location (probably from the finder)
  1944.                 FSSpec dropFSSpec;
  1945.                 
  1946.                 result = GetDropFSSpec(theDrag, dropFSSpec);
  1947.                 if (result == noErr)
  1948.                 {
  1949.                     ODSShort    mouseDownModifiers;
  1950.                     ODSShort    mouseUpModifiers;
  1951.                                 
  1952.                     GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  1953.  
  1954.                     // Check the mandatory modifier keys first
  1955.                         
  1956.                     if (mouseUpModifiers & controlKey)
  1957.                         self->SetDropResult(ev, kODDropMove);    // Need to take care of moving to the Finder.
  1958.                     else
  1959.                         self->SetDropResult(ev, kODDropFail);    // Copied to non OpenDoc process, so return fail so part will
  1960.                                                                 // not post undo action.    
  1961.                     boolean nameFromPart = MakeUniqueFilename(ev, self->GetSession(ev), theDragItem->GetStorageUnit(ev), &dropFSSpec);
  1962.                     
  1963.                     // Drags to the Trash are always a move
  1964.                     boolean isDraggingToTrash = IsTrashFolder(dropFSSpec);
  1965.     
  1966.                     if (isDraggingToTrash)
  1967.                     {
  1968.                         self->SetDropResult(ev, kODDropMove);   // Dragged to Trash, so it's a move.
  1969.  
  1970.                         TempPlatformFile file = new PlatformFile;
  1971.                         file->Specify(&dropFSSpec);
  1972.     
  1973.                         if (file->Exists())
  1974.                         {
  1975.                             // If the target file exists in trash already,
  1976.                             // set the fsspec to the temp folder.
  1977.                             RespecifyToTempFolder(file);
  1978.                             
  1979.                             // Clone the data.
  1980.                             CloneIntoFile(ev, theDragItem, file->GetFileSpec());
  1981.                             
  1982.                             // After cloning the data to the file (in temp folder),
  1983.                             // move to it trash.
  1984.                             file->MoveToTrash();
  1985.                             
  1986.                             // Set the result for Drag Manager.
  1987.                             SetDragItemFlavorData(theDrag, theItem, theType, &(file->GetFileSpec()), sizeof(FSSpec), 0L);
  1988.                         }
  1989.                         else
  1990.                         {    
  1991.                             CloneIntoFlavor(ev, self, theDragItem,
  1992.                                             theDrag, theItem, theType,
  1993.                                             dropFSSpec);
  1994.                         }
  1995.                     }
  1996.                     else if (!nameFromPart)
  1997.                     {
  1998.                         CloneIntoFlavor(ev, self, theDragItem,
  1999.                                         theDrag, theItem, theType,
  2000.                                         dropFSSpec);
  2001.                     }
  2002.                     else if (IsFrontProcess())
  2003.                     {
  2004.                         TempPlatformFile file = new PlatformFile;
  2005.                         file->Specify(&dropFSSpec);
  2006.     
  2007.                         if (file->Exists())
  2008.                         {
  2009.                             ParamText(dropFSSpec.name, "\p", "\p", "\p");
  2010.                             if (ODAskUserReplace(ev, self->GetSession(ev)))
  2011.                             {                        
  2012.                                 file->MoveToTrash();
  2013.                                 CloneIntoFlavor(ev, self, theDragItem,
  2014.                                                 theDrag, theItem, theType,
  2015.                                                 dropFSSpec);
  2016.                             }
  2017.                         }
  2018.                         else
  2019.                         {
  2020.                             CloneIntoFlavor(ev, self, theDragItem,
  2021.                                             theDrag, theItem, theType,
  2022.                                             dropFSSpec);
  2023.                         }
  2024.                     }
  2025.                     else
  2026.                     {
  2027.                         TempPlatformFile file = new PlatformFile;
  2028.                         file->Specify(&dropFSSpec);
  2029.                         
  2030.                         if (file->Exists())
  2031.                         {
  2032.                             FSSpec targetFSSpec = file->GetFileSpec();
  2033.                             RespecifyToTempFolder(file);
  2034.                             FSSpec tmpFileFSSpec = file->GetFileSpec();
  2035.                             CloneIntoFile(ev, theDragItem, tmpFileFSSpec);
  2036.                             // Not notifying the target through SetDragItemData on purpose becuase we are going all the work.
  2037.                             
  2038.                             gTargetFSSpec = targetFSSpec;
  2039.                             gTmpFileFSSpec = tmpFileFSSpec;
  2040.                             self->SetShouldSendReplaceFileEvent(ev, kODTrue);
  2041.                         }
  2042.                         else
  2043.                         {
  2044.                             CloneIntoFlavor(ev, self, theDragItem,
  2045.                                         theDrag, theItem, theType,
  2046.                                         dropFSSpec);
  2047.                         }                
  2048.                     }
  2049.                 }
  2050.                 // If we are not dragging to a file, create a Drag item for the Bento Container.
  2051.                 // This allows other applications to support OpenDoc Bento types (like the Scrapbook, 
  2052.                 // or Container apps).
  2053.                 else if ( result == fnfErr )
  2054.                 {
  2055.                     ODULong dropResult;
  2056.  
  2057.                     // At this point, Doug says only a memory container is being
  2058.                     // modified in any way, so we can suppress fatal errors:
  2059.                     TempSuppressFatalBentoError tempSuppress;
  2060.                     
  2061.                     ODSShort    mouseDownModifiers;
  2062.                     ODSShort    mouseUpModifiers;
  2063.                             
  2064.                     GetDragModifiers(self->GetDragReference(ev), 0L, &mouseDownModifiers, &mouseUpModifiers);
  2065.  
  2066.                     // Check the mandatory modifier keys first. We want to allow moving to a non-OpenDoc process,
  2067.                     // instead of just copies.
  2068.                     
  2069.                     if (mouseUpModifiers & controlKey) 
  2070.                         dropResult = kODDropMove;
  2071.                     else
  2072.                         dropResult = kODDropCopy;
  2073.                     
  2074.                     OSErr e = 
  2075.                     CopyMemContainerToDragItemInChunks( ev, self->GetSession(ev), theType, theItem, theDrag, theDragItem );
  2076.  
  2077.                     dropResult = kODDropFail;        // Dragged to non OpenDoc process, so return fail so part will
  2078.                                                     // post undo action.    
  2079.                     self->SetDropResult(ev, dropResult);
  2080.                     return e;
  2081.                 }
  2082.             }
  2083.             break;
  2084.             default:
  2085. #ifdef ODDebug_DragAndDrop
  2086.     somPrintf("MySendDataProc: Default\n");
  2087. #endif
  2088.                 self->SetDropResult(ev, kODDropFail);
  2089.                 translate = self->GetSession(ev)->GetTranslation(ev);
  2090.                 theISOType = translate->GetISOTypeFromPlatformType(ev, theType, kODPlatformDataType);
  2091.                 if (ODSUExistsThenFocus(ev, theDragItem->GetStorageUnit(ev),kODPropContents, theISOType))
  2092.                 {
  2093.                     result = CopyToDragItemInChunks(ev, theType, theItem, theDrag, theDragItem);
  2094.                     if (result == noErr)
  2095.                         self->SetDropResult(ev, kODDropCopy);
  2096.                 }
  2097.                 else if ( (theType == kODScrapTypestyl) && StorageUnitGetStylFromStyledText(theDragItem->GetStorageUnit(ev), ev, &stylSize, &stylPtr) )
  2098.                 {
  2099.                     result = SetDragItemFlavorData(theDrag, theItem, theType, stylPtr, stylSize, 0L);
  2100.                     WASSERTM(result == noErr, "Error from SetDragItemFlavorData in send procedure");        
  2101.                     if (result == noErr)
  2102.                         self->SetDropResult(ev, kODDropCopy);
  2103.                     ODDisposePtr(stylPtr);
  2104.                     stylPtr = kODNULL;
  2105.                 }
  2106.                 else
  2107.                 {
  2108.                     WARN("Send procedure can not supply this type");        
  2109.                     result = badDragFlavorErr;
  2110.                 }
  2111.                 ODDisposePtr(theISOType);
  2112.             }
  2113.         }
  2114.  
  2115.     CATCH_ALL
  2116.     
  2117.     self->SetShouldSendReplaceFileEvent(ev, kODFalse);
  2118.     result = ErrorCode();
  2119.     WARN("MySendDataProc: %d", result); 
  2120.     
  2121.     ENDTRY
  2122.     
  2123.     return result;
  2124. }
  2125.  
  2126. static OSErr CopyMemContainerToDragItemInChunks(Environment* ev,
  2127.                                 ODSession* theSession,
  2128.                                 FlavorType theType,
  2129.                                 ItemReference theItem,
  2130.                                 ODPlatformDragReference theDrag,
  2131.                                 ODDragItem* theDragItem) 
  2132. {
  2133.     const ODULong kCopyBlockSize = 512;
  2134.     OSErr    result = noErr;
  2135.     ODPtr     dataPtr;
  2136.     ODULong dataSize;
  2137.     
  2138.     TRY
  2139.         // Now write out the entire Container for the Memory Drag item.
  2140.         ODMemDragItem* tempDItem = (ODMemDragItem*)theDragItem;
  2141.  
  2142.         // Clone the D&D container to a temp draft, then return the data handle from the temp container.
  2143.         // We cannot directly get the data handle from the D&D container, because the full data isn't written
  2144.         // until we close the container, but we can't do that yet because there could be further promises
  2145.         // pending against it.
  2146.         TempODHandle theMemDragItemContainerData = CloneToTempMemContainer( ev,  tempDItem, theSession );        
  2147.  
  2148.         ODLockHandle( theMemDragItemContainerData );
  2149.     
  2150.         dataPtr = *theMemDragItemContainerData;
  2151.         dataSize = ODGetHandleSize( theMemDragItemContainerData );
  2152.         WASSERTM( dataSize != 0, "Zero size memory container handle.");        
  2153.  
  2154.         ODULong currentByte = 0;
  2155.         while ((currentByte < dataSize) && (result == noErr)) {
  2156.             ODULong bytesRead;
  2157.             if( ( dataSize - currentByte )  >= kCopyBlockSize )
  2158.                 bytesRead = kCopyBlockSize;
  2159.             else
  2160.                 bytesRead = dataSize - currentByte;
  2161.                 
  2162.             result = SetDragItemFlavorData(theDrag, theItem, theType, ODPtr((ODULong)dataPtr + currentByte), bytesRead, currentByte);
  2163.             WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  2164.             currentByte += bytesRead;
  2165.         }
  2166.         WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  2167.     CATCH_ALL
  2168.         result = dragNotAcceptedErr;
  2169.     ENDTRY
  2170.     return result;
  2171. }
  2172.  
  2173. static ODHandle CloneToTempMemContainer( Environment* ev, ODMemDragItem* tempDItem, ODSession* theSession )
  2174. {
  2175.     ODStorageUnit* contentSU = tempDItem->GetStorageUnit(ev);
  2176.     ODID targetContentFrameID = kODNULLID;
  2177.     ODHandle containerHandle =    ODNewHandle(0);
  2178.     ODStorageUnitID suID;
  2179.     TRY
  2180.         TempODContainer        tempContainer = CreateMemoryContainer(ev, theSession, containerHandle, kODBentoMemoryContainer);        
  2181.         TempODDocument         tempDocument = tempContainer->AcquireDocument(ev, kODDefaultDocument);
  2182.         TempODDraft         targetDraft = tempDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  2183.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  2184.  
  2185.         { TempODStorageUnit draftProperties = targetDraft->AcquireDraftProperties(ev);
  2186.           ODSetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef,targetSU->GetID(ev));
  2187.           suID = ODGetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef);
  2188.         }
  2189.         
  2190.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  2191.         ODDraftKey cloneKey = 0;
  2192.         TRY
  2193.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  2194.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  2195.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  2196.             if (contentFrameID != kODNULLID) 
  2197.             {
  2198.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  2199.             }        
  2200.             sourceDraft->EndClone(ev, cloneKey);
  2201.         CATCH_ALL
  2202.             sourceDraft->AbortClone(ev, cloneKey);
  2203.             
  2204.         ENDTRY
  2205.         
  2206.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);    
  2207.  
  2208.         // first externalize the container 
  2209.         // Externalize may fail with an iterator-out-of-sync error because 
  2210.         // resolving promises may add storage units to the draft's collection
  2211.         // during iteration.  In theory, the only promises should be in the
  2212.         // root storage unit, so explicitly externalize it first to resolve
  2213.         // promises before interating over all storage units.
  2214.         if( targetSU )
  2215.             targetSU->Externalize(ev);
  2216.         targetDraft->Externalize(ev);
  2217.         
  2218.     CATCH_ALL
  2219.         ODDisposeHandle( containerHandle );
  2220.         RERAISE;
  2221.     ENDTRY
  2222.     
  2223.     return containerHandle; 
  2224. }
  2225.  
  2226. static void CloneIntoFlavor(Environment* ev, ODDragAndDrop* dad, ODDragItem* theDragItem, 
  2227.                                 ODPlatformDragReference theDrag, ItemReference theItem, FlavorType theType,
  2228.                                 FSSpec dropFSSpec)
  2229. {
  2230.     OSErr result;
  2231.     
  2232.     if ((result = CloneIntoFile(ev, theDragItem, dropFSSpec)) == noErr)
  2233.     {
  2234.         result = SetDragItemFlavorData(theDrag, theItem, theType, &dropFSSpec, sizeof(FSSpec), 0L);
  2235.     }
  2236.     else
  2237.     {
  2238.         dad->SetDropResult(ev, kODDropFail);                
  2239.     }                
  2240. }
  2241.  
  2242. static OSErr CloneIntoFile(Environment* ev, ODDragItem* theDragItem, FSSpec dropFSSpec) 
  2243. {
  2244.     OSErr            err = noErr;
  2245.     PlatformFile    file;
  2246.     file.Specify(&dropFSSpec);
  2247.     
  2248.     TRY
  2249.         ODStorageUnit* contentSU = theDragItem->GetStorageUnit(ev);
  2250.         ODID targetContentFrameID = kODNULLID;
  2251.         OSType    fileType = GetStorageUnitOSType(ev,contentSU);
  2252.         OSType    fileCreator=ODGetIconFilePlatformCreatorFromPartSU(ev,contentSU);
  2253.  
  2254.         file.Create(fileCreator, fileType, smSystemScript);
  2255.         SetFinderInfo(ev, contentSU, &file);
  2256.         SetIconFamily(ev, contentSU, &file);
  2257.         TempODContainer targetContainer    = CreateFileContainer(ev, contentSU->GetSession(ev), &file.GetFileSpec());
  2258.         TempODDocument    targetDocument    = targetContainer->AcquireDocument(ev, kODDefaultDocument);
  2259.         TempODDraft        targetDraft     = targetDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
  2260.         TempODStorageUnit     targetDraftProperties = targetDraft->AcquireDraftProperties(ev);
  2261.         TempODStorageUnit    targetSU    = targetDraft->CreateStorageUnit(ev);
  2262.         ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootPartSU,kODStrongStorageUnitRef, targetSU->GetID(ev));
  2263.         ODDraft* sourceDraft = contentSU->GetDraft(ev);                
  2264.         ODDraftKey cloneKey = 0;
  2265.         TRY
  2266.             cloneKey = sourceDraft->BeginClone(ev, targetDraft, kODNULL, kODCloneToFile);
  2267.             sourceDraft->Clone(ev, cloneKey, contentSU->GetID(ev), targetSU->GetID(ev), 0);                
  2268.             ODID contentFrameID = ODGetWeakSURefProp(ev, contentSU, kODPropContentFrame, kODWeakStorageUnitRef);
  2269.             if (contentFrameID != kODNULLID) 
  2270.             {
  2271.                 targetContentFrameID = sourceDraft->Clone(ev, cloneKey, contentFrameID, kODNULLID, 0);                
  2272.             }        
  2273.             sourceDraft->EndClone(ev, cloneKey);
  2274.         CATCH_ALL
  2275.             sourceDraft->AbortClone(ev, cloneKey);
  2276.         ENDTRY
  2277.         
  2278.         if (targetContentFrameID != kODNULLID)
  2279.             ODSetStrongSURefProp(ev, targetDraftProperties, kODPropRootFrameList, kODStrongStorageUnitRefs, targetContentFrameID);
  2280.  
  2281.         ODSURemoveProperty(ev, targetSU, kODPropMouseDownOffset);
  2282.  
  2283.         targetDraft->Externalize(ev);        
  2284.     CATCH_ALL
  2285.     
  2286.         file.Delete();        
  2287.         err = dragNotAcceptedErr;
  2288.         WARN("Error caught in CloneIntoFile.");
  2289.     ENDTRY
  2290.     
  2291.     return err;
  2292. }
  2293.  
  2294. static boolean MakeUniqueFilename( Environment *ev, ODSession* session, ODStorageUnit *su, FSSpec* spec )
  2295. {    
  2296.     Str255 prefix;
  2297.     prefix[0] = 0;
  2298.     boolean nameFromPart = false;
  2299.     TempPlatformFile file = new PlatformFile;
  2300.     file->Specify(spec);
  2301.     
  2302.     TRY
  2303.         // Get the name of the part
  2304.         if (su->Exists(ev, kODPropName, kODMacIText, 0))
  2305.         {
  2306.             ODIText* rootPartName = ODGetITextProp(ev, su, kODPropName, kODMacIText, kODNULL);
  2307.             if (rootPartName)
  2308.             {
  2309.                 GetITextPString(rootPartName, prefix);
  2310.                 DisposeIText(rootPartName);
  2311.                 if( prefix[0] > kODMaxFileNameSize )
  2312.                     ClipStringToBytes( prefix, kODMaxFileNameSize, smCurrentScript );
  2313.                 p2cstr(prefix);
  2314.                 file->SetAsciiName((char*) prefix);    
  2315.                 nameFromPart = true;
  2316.             }
  2317.         }
  2318.     
  2319.         if (!prefix[0])
  2320.         {        
  2321.             // Get the category of the part if a name cannot be found.
  2322.             ODName* categoryName = kODNULL;
  2323.             TRY
  2324.                 categoryName = ODGetCatFromPartSU(ev, su, session->GetNameSpaceManager(ev));
  2325.             CATCH_ALL
  2326.             ENDTRY
  2327.             // If the above call throws, then most likely we were trying to get the category for NoPart.
  2328.             // So, set the category name for NoPart appropriately.
  2329.             if( !categoryName)
  2330.             {
  2331.                 ODGetString( prefix, kODUnknownCategoryStr );
  2332.                 p2cstr(prefix);
  2333.             }
  2334.             if (categoryName)
  2335.             {
  2336.                 GetITextPString(categoryName, prefix);
  2337.                 p2cstr(prefix);
  2338.             }
  2339.             file->SetAsciiName((char*) prefix);    
  2340.             file->UniquifyName(kODNoResourceID,
  2341.                                 kODNULL,
  2342.                                 kODCategoryNumberSuffix,
  2343.                                 kODNULL,
  2344.                                 1,
  2345.                                 kSpecifyNewNameOnly,
  2346.                                 kODForceNewName);
  2347.             ODDisposePtr(categoryName);
  2348.             nameFromPart = false;
  2349.         }
  2350.     CATCH_ALL
  2351.     ENDTRY
  2352.         
  2353.     *spec = file->GetFileSpec();
  2354.     return nameFromPart;
  2355. }
  2356.  
  2357. static OSType GetStorageUnitOSType( Environment *ev, ODStorageUnit *su )
  2358. {
  2359.     OSType    returnType = kODShellSignature;
  2360.  
  2361. #if ODDebug_DragAndDrop
  2362.     ODULong    numProperties = su->CountProperties(ev);
  2363.     su->Focus(ev, kODNULL, kODPosAll, kODNULL, 0, kODPosAll);
  2364.     for (ODULong i = 1; i <= numProperties; i++) {
  2365.         su->Focus(ev, kODNULL, kODPosNextSib,kODNULL,0,kODPosAll);
  2366.         ODPropertyName name = su->GetProperty(ev);
  2367.         ODDisposePtr(name);
  2368.     }
  2369. #endif
  2370.     
  2371.     returnType = ODGetIconFilePlatformTypeFromPartSU(ev, su);
  2372.     
  2373.     return returnType;
  2374. }
  2375.  
  2376.  
  2377. static OSErr CopyToDragItemInChunks(Environment* ev,
  2378.                                 FlavorType theType,
  2379.                                 ItemReference theItem,
  2380.                                 ODPlatformDragReference theDrag,
  2381.                                 ODDragItem* theDragItem) 
  2382. {
  2383.     const ODULong kCopyBlockSize = 512;
  2384.     OSErr    result = noErr;
  2385.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2386.     ODULong dataSize = theDragItem->GetStorageUnit(ev)->GetSize(ev);
  2387.     
  2388.     ODULong currentByte = 0;
  2389.     while ((currentByte < dataSize) && (result == noErr)) {
  2390.         ODULong bytesRead = StorageUnitGetValue(theDragItem->GetStorageUnit(ev), ev, kCopyBlockSize, dataPtr);
  2391.         result = SetDragItemFlavorData(theDrag, theItem, theType, dataPtr, bytesRead, currentByte);
  2392.         WASSERTM(result == noErr, "Error from SetDragItemFlavorData in CopyToDragItemInChunks.");        
  2393.         currentByte += bytesRead;
  2394.     }
  2395.     ODDisposePtr(dataPtr);
  2396.     WASSERTM(currentByte == dataSize, "Bytes written is NOT equal to dataSize.");        
  2397.     
  2398.     return result;
  2399. }
  2400.  
  2401. static OSErr CopyFromDragItemInChunks(Environment* ev,
  2402.                                 FlavorType theType,
  2403.                                 ItemReference theItem,
  2404.                                 ODPlatformDragReference theDrag,
  2405.                                 ODStorageUnitView* destSUView) 
  2406. {
  2407.     const ODULong kCopyBlockSize = 512;
  2408.     OSErr    result = noErr;
  2409.     ODPtr     dataPtr = ODNewPtr(kCopyBlockSize);
  2410.     long    dataSize = 0;
  2411.     ODULong    totalRead = 0;
  2412.     ODULong    oldValueSize = destSUView->GetSize(ev);
  2413.     
  2414.     result = GetFlavorDataSize(theDrag, theItem, theType, &dataSize);
  2415.     while ((totalRead < dataSize) && (result == noErr)) {
  2416.         Size bytesRead = dataSize - totalRead;
  2417.         if (bytesRead > kCopyBlockSize)
  2418.             bytesRead = kCopyBlockSize;
  2419.         result = GetFlavorData(theDrag, theItem, theType, dataPtr, &bytesRead, totalRead);
  2420.         WASSERTM(result == noErr, "Error from GetFlavorData in CopyFromDragItemInChunks.");        
  2421.         StorageUnitViewSetValue(destSUView, ev, bytesRead, dataPtr);
  2422.         totalRead += bytesRead;
  2423.     }
  2424.     ODDisposePtr(dataPtr);
  2425.  
  2426.     ODULong newValueSize = destSUView->GetOffset(ev);
  2427.     if (oldValueSize > newValueSize)
  2428.         destSUView->DeleteValue(ev, oldValueSize - newValueSize);
  2429.  
  2430.     return result;
  2431. }
  2432.  
  2433.  
  2434. #ifdef ODDebug_DragAndDrop
  2435. void PrintDragReference(ODPlatformDragReference dragRef, char* header)
  2436. {
  2437.     unsigned short    items = 0;
  2438.     CountDragItems(dragRef, &items);
  2439.     somPrintf("%s: fDragReference %x numItems %d\n", header, dragRef, items);
  2440.     for (unsigned short i = 1; i <= items; i++) {
  2441.         ItemReference    itemRef;
  2442.         GetDragItemReferenceNumber(dragRef, i, &itemRef);
  2443.         unsigned short numFlavors = 0;
  2444.         CountDragItemFlavors(dragRef, itemRef, &numFlavors);
  2445.         FlavorType theType;
  2446.         Size    dataSize = 0;
  2447.         for (unsigned short j = 1; j <= numFlavors; j++) {
  2448.             GetFlavorType (dragRef, itemRef, j, &theType);
  2449.             GetFlavorDataSize(dragRef, itemRef, theType, &dataSize);
  2450.             somPrintf("%s: itemRef %x item %d flavor %d size %d type ", header, itemRef, i, j, dataSize);
  2451.             for (short k = 0; k <= 3; k++) {
  2452.                 somPrintf("%c", ((char*) &theType)[k]);
  2453.             }
  2454.             somPrintf("\n");
  2455.             if ((theType == 'hfs ') && (dataSize > 0)) {
  2456.                 HFSFlavor hfsFlavor;
  2457.                 GetFlavorData(dragRef,itemRef,theType,&hfsFlavor,&dataSize,0);
  2458.                 somPrintf("type %x creator %x name %s\n", hfsFlavor.fileType, hfsFlavor.fileCreator, p2cstr(hfsFlavor.fileSpec.name));
  2459.             }
  2460.         }
  2461.     }
  2462. }
  2463.  
  2464. void PrintStorageUnit(Environment* ev, ODStorageUnit* su, char* header)
  2465. {
  2466.     ODStorageUnitCursor* cursor = su->CreateCursorWithFocus(ev);
  2467.     
  2468.     ODULong numProperties = su->CountProperties(ev);
  2469.     su->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
  2470.     ODULong numValues = su->CountValues(ev);
  2471.     somPrintf("%s: su %x numProperties %d numContentValues %d\n", header, su, numProperties, numValues);
  2472.     for (short i = 1; i <= numValues; i++) {
  2473.         su->Focus(ev, kODNULL, kODPosSame, kODNULL, i, kODPosUndefined);
  2474.         ODValueType type = su->GetType(ev);
  2475.         somPrintf("%s: Type %d %s\n", header, i, type);
  2476.         ODDisposePtr(type);
  2477.     }
  2478.     
  2479.     su->FocusWithCursor(ev, cursor);
  2480.     delete cursor;
  2481. }
  2482.  
  2483. #endif
  2484.  
  2485. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterHandler(ODDragAndDrop *somSelf, Environment *ev,
  2486.         ODPlatformDragReference theDrag)
  2487. {
  2488. // $$$$$ - dh: Need to make sure that this can be safely called during a drag twice. Also, we 
  2489. // should make sure that this routine does the work of setting private object fields, not 
  2490. // CreateDragItemIterator.
  2491.  
  2492.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2493.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterHandler");
  2494.  
  2495. #if ODDebug_DragAndDrop
  2496.     somPrintf("In EnterHandler.\n");
  2497. #endif        
  2498.  
  2499.     OSErr            returnCode = noErr;
  2500.     ODUShort        dragItems = 0;
  2501.     ODVolatile(returnCode);
  2502.  
  2503.     SOM_TRY
  2504.         returnCode = CountDragItems(theDrag, &dragItems);
  2505.         if( returnCode == noErr )
  2506.         {
  2507.             SOM_TRY
  2508.                 somSelf->CreateDragItemIterator(ev, theDrag, 1, dragItems);
  2509.             SOM_CATCH_ALL
  2510.                 returnCode = ErrorCode();
  2511.             SOM_ENDTRY
  2512.         }
  2513.     
  2514.         ODDeleteObject(_fFacetsRejected);
  2515.         
  2516.     SOM_CATCH_ALL    
  2517.     
  2518.         returnCode = ErrorCode();
  2519.         ODDeleteObject(_fFacetsRejected);
  2520.         if (_fDragItemList)
  2521.             _fDragItemList->DeleteAllLinks();
  2522.         
  2523.     SOM_ENDTRY
  2524.     
  2525.     _fFacetsRejected = new OpenHashTable(OpenHashTable::StdEqual, OpenHashTable::StdHash, kODNULL);
  2526.     _fFacetsRejected->Initialize(kODInitialNumEntries,
  2527.                                     sizeof(ODFacet*),
  2528.                                     sizeof(ODFacet*));
  2529.     
  2530.     return returnCode;
  2531. }
  2532.  
  2533. SOM_Scope OSErr  SOMLINK ODDragAndDropEnterWindow(ODDragAndDrop *somSelf, Environment *ev,
  2534.         ODPlatformDragReference theDrag,
  2535.         ODPlatformWindow theWindow)
  2536. {
  2537.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2538.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropEnterWindow");
  2539.     
  2540.     // This is a private method called only from MyDragTrackingHandler.
  2541.     // It can do without its own SOM_TRY.
  2542.  
  2543. #if ODDebug_DragAndDrop
  2544.     somPrintf("Enter EnterWindow.\n");
  2545. #endif
  2546.  
  2547.     ODPoint            mouse, localMouse;
  2548.     Point            qdMouse;
  2549.     ODFacet*        targetFacet = kODNULL;
  2550.     ODBoolean        handled = kODFalse;
  2551.     
  2552.     GetDragMouse(theDrag, &qdMouse, 0L);
  2553.     mouse = qdMouse;
  2554.     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2555.     
  2556.     if (!targetFacet)
  2557.         _fAttributes &= kODDragHasLeftSourcePartMask;
  2558.     else
  2559.     {
  2560.         while (targetFacet && !handled)
  2561.         {
  2562.             if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2563.                 _fAttributes |= kODDragIsInSourcePart;
  2564.                 _fAttributes |= kODDragIsInSourceFrame;
  2565.             }
  2566.             else
  2567.             {
  2568.                 _fHasLeftSourceFrame = kODTrue;
  2569.                 ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2570.                 if (targetPart == _fSourcePart)
  2571.                     _fAttributes = kODDragIsInSourcePart;
  2572.                 else {
  2573.                     _fHasLeftSourcePart = kODTrue;
  2574.                     _fAttributes = 0;
  2575.                 }
  2576.                 ODReleaseObject(ev, targetPart);
  2577.             }
  2578.             handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2579.             if (!handled)
  2580.             {
  2581.                 _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet);
  2582.                 targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2583.             }
  2584.         }
  2585.     }
  2586.     _fPrevFacet = targetFacet;
  2587.     
  2588.     return noErr;
  2589. }
  2590.  
  2591. SOM_Scope OSErr  SOMLINK ODDragAndDropInWindow(ODDragAndDrop *somSelf, Environment *ev,
  2592.         ODPlatformDragReference theDrag,
  2593.         ODPlatformWindow theWindow)
  2594. {
  2595.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2596.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropInWindow");
  2597.  
  2598.     ODPoint            mouse, localMouse;
  2599.     Point            qdMouse;
  2600.     ODFacet*        targetFacet = kODNULL;
  2601.     ODBoolean        handled = kODFalse;
  2602.     
  2603.     SOM_TRY
  2604.     
  2605.         GetDragMouse(theDrag, &qdMouse, 0L);
  2606.         mouse = qdMouse;
  2607.         // Get the facet under the current mouse location.
  2608.         targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2609.         
  2610.         // We are leaving the window, call DragLeave on the last facet and return
  2611.         if (!targetFacet) {
  2612.             _fAttributes &= kODDragHasLeftSourcePartMask;
  2613.             if (_fPrevFacet) {
  2614.                 _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2615.             }
  2616.         }
  2617.         // Otherwise, the mouse is still in the OpenDoc window.
  2618.         else
  2619.         {    
  2620.             // Since the mouse is still in the OpenDoc window, we want to implement the following protocal for
  2621.             // having different facets draw drag highlighting. Everytime the mouse moves and is still in the window:
  2622.             // A. If the mouse enters a new facet, call DragEnter on the new one.
  2623.             //       1. If the new facet can't accept the drag, call DragEnter on the next containg facet.
  2624.             // B. If the mouse stays within the same facet, call DragWithin on that facet again.
  2625.             // C. If the mouse leaves a facet, call DragLeave on the facet.
  2626.             // We don't want drag-highlighiting to take place on the frame that originates the drag,
  2627.             // unless the mouse leaves the frame, then enters it again. So, we do the following:
  2628.             //    1. Store a refernce to the frame that originated the drag..
  2629.             //      2. Define a boolean that signifies that the mouse has not left the source frame.
  2630.             //      3. While the mouse is still in the source frame, tell the part not to do any drag-hiliting as above.
  2631.             //      4. When the mouse leaves the source frame, set the boolean that signifies we have not left the source
  2632.             //         to false. This tells subsequent parts to do hilighting following the above algorithm.
  2633.  
  2634.             // We basically want to do one of the following in this loop:
  2635.             //    1. Track that the mouse has entered a new facet and call DragEnter on it.
  2636.             //    2. Track that the mouse has left a facet and call DragLeave on it.
  2637.             //    3. Track that the mouse is still in a facet and call DragWithin on it.
  2638.             // Obviously there are special cases to all of the above. See the source comments below for more info.
  2639.             while (targetFacet && !handled)
  2640.             {   
  2641.                 // Check whether we are still in the source frame, and haven't ever left it. If so, no hiliting needed.
  2642.                 if ((targetFacet->GetFrame(ev) == _fSourceFrame) && (_fHasLeftSourceFrame == kODFalse)) {
  2643.                     _fAttributes |= kODDragIsInSourcePart;
  2644.                     _fAttributes |= kODDragIsInSourceFrame;
  2645.                 }
  2646.                 // Otherwise, we are either in a new frame, or we have left and reenter the source frame. 
  2647.                 // Tell the part to start doing hiliting.
  2648.                 else {
  2649.                     _fHasLeftSourceFrame = kODTrue;
  2650.                     ODPart* targetPart = targetFacet->GetFrame(ev)->AcquirePart(ev);
  2651.                     if (targetPart == _fSourcePart)
  2652.                         _fAttributes = kODDragIsInSourcePart;
  2653.                     else {
  2654.                         _fHasLeftSourcePart = kODTrue;
  2655.                         _fAttributes = 0;
  2656.                     }
  2657.                     ODReleaseObject(ev, targetPart);
  2658.                 }
  2659.                 if (_fPrevFacet == targetFacet)  {
  2660.                     handled = targetFacet->DragWithin(ev, &localMouse, _fDragItemIterator, kODNULL);
  2661.                 }
  2662.                 else {
  2663.                 // We need to call DragLeave on the previous facet before we call DragEnter on the new one, even
  2664.                 // though the DragEnter can return false. Why not call DragEnter first, decide if it succeeds, then
  2665.                 // call DragLeave? Because of ShowDragHilite and HideDragHilite Drag Manager functions need this
  2666.                 // order or drag hiliting is messed up.
  2667.                     if( _fPrevFacet )
  2668.                         _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2669.                     handled = targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2670.     //                if ( _fPrevFacet && !handled ) {
  2671.     //                    targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2672.     //                }
  2673.                 }
  2674.                 if (!handled)
  2675.                 {
  2676.                 // If any facet rejects a particular drag, then at no time during the current will it ever
  2677.                 // accept it again. A part can only handle certain drag kinds, and that will not change during
  2678.                 // a drag. So, if a drag is rejected, keep a list of facets that have rejected the current
  2679.                 // drag and don't try to do hiliting for them again for this drag.
  2680.                     _fFacetsRejected->ReplaceEntry(&targetFacet, &targetFacet); 
  2681.                     // On of the following happened previous to this statement:
  2682.                     // DragWithin or DragEnter was called on a facet and the part returned false.
  2683.                     // So, give the container a crack at the drag.
  2684.                     targetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2685.                     if( targetFacet )
  2686.                         targetFacet->DragEnter(ev, &localMouse, _fDragItemIterator, kODNULL);
  2687.                     // else the root rejected the drag and there is no container to take the drag. Will just
  2688.                     // exit this loop.
  2689.                 }
  2690.             }
  2691.         }
  2692.         _fPrevFacet = targetFacet;
  2693.     
  2694.     SOM_CATCH_ALL
  2695.     SOM_ENDTRY
  2696.  
  2697.     return noErr;
  2698. }
  2699.  
  2700. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveWindow(ODDragAndDrop *somSelf, Environment *ev,
  2701.         ODPlatformDragReference theDrag,
  2702.         ODPlatformWindow theWindow)
  2703. {
  2704.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2705.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveWindow");
  2706.  
  2707. #if ODDebug_DragAndDrop
  2708.     somPrintf("In LeaveWindow.\n");
  2709. #endif        
  2710.  
  2711.     SOM_TRY
  2712.         ODPoint            mouse, localMouse;
  2713.         Point            qdMouse;
  2714.         
  2715.         GetDragMouse(theDrag, &qdMouse, 0L);
  2716.         mouse = qdMouse;
  2717.         ODFacet* dummyTargetFacet = somSelf->FindTargetFacet(ev, theWindow, &mouse, &localMouse);
  2718.     
  2719.         _fAttributes = 0;
  2720.         if (_fPrevFacet) {
  2721.             _fPrevFacet->DragLeave(ev, &localMouse, kODNULL);
  2722.             _fPrevFacet = kODNULL;
  2723.         }
  2724.     SOM_CATCH_ALL
  2725.     SOM_ENDTRY
  2726.     
  2727.     _fHasLeftSourceFrame = kODTrue;
  2728.     _fHasLeftSourcePart = kODTrue;
  2729.  
  2730.     return noErr;
  2731. }
  2732.  
  2733. SOM_Scope OSErr  SOMLINK ODDragAndDropLeaveHandler(ODDragAndDrop *somSelf, Environment *ev)
  2734. {
  2735.     ODDragAndDropData *somThis = ODDragAndDropGetData(somSelf);
  2736.     ODDragAndDropMethodDebug("ODDragAndDrop","ODDragAndDropLeaveHandler");
  2737.  
  2738. #if ODDebug_DragAndDrop
  2739.     somPrintf("In LeaveHandler.\n");
  2740. #endif        
  2741.     
  2742.     // Now undo the damage done in the dragTrackingEnterHandler section.
  2743.     // NOTE: It is OK to blow away the drag items here because at this point
  2744.     // the drop handler will already have processed the drop if any.
  2745.  
  2746.     if (_fListFromHandler)
  2747.     {
  2748.         TRY{
  2749.             somSelf->Clear(ev);
  2750.         }CATCH_ALL{
  2751.             // ignore error
  2752.         }ENDTRY
  2753.         _fListFromHandler = kODFalse;
  2754.         _fDragReference = 0;
  2755.     }
  2756.     _fAttributes = 0;
  2757.     
  2758.     return noErr;
  2759. }
  2760.  
  2761. static void    SetIconFamily(Environment* ev, ODStorageUnit* fromSU, PlatformFile* file)
  2762. {
  2763.     static const ResType            kIconType[6] = {'ICN#','icl4','icl8','ics#','ics4','ics8'};
  2764.     static const short                kIconSize[6] = {256,   512,   1024,  64,    128,   256   };
  2765.      ODIconFamily icons = ODGetIconFamilyProp(ev, fromSU, kODPropCustomIcon, kODIconFamily, kAllIconsMask);
  2766.     
  2767.     if (icons)
  2768.     {
  2769.         // write icons to the file
  2770.         long    i = 6;
  2771.         do {
  2772.             Handle    icon;
  2773.             char    state;
  2774.             if ((GetIconFromSuite(&icon, icons, kIconType[--i]) == noErr) && (icon != nil))
  2775.             {
  2776.                 state = HGetState(icon);
  2777.                 HLock(icon);
  2778.                 WASSERT(GetHandleSize(icon) == kIconSize[i]);
  2779.                 file->WriteResourcePtr(kIconType[i], kCustomIconResource, *icon, kIconSize[i]);
  2780.                 HSetState(icon, state);
  2781.             }
  2782.         } while (i);
  2783.         file->SetCustomIcon(kODTrue);
  2784.     }
  2785. }
  2786.  
  2787. static void SetFinderInfo(Environment* ev, ODStorageUnit* su, PlatformFile* file)
  2788. {
  2789.     InitDateInfo(ev, su);
  2790.     ODULong modDate = ODGetModificationDate(ev, su);
  2791.     ODULong creationDate = ODGetCreationDate(ev, su);        
  2792.     
  2793.     file->CreateResFile();    
  2794.     file->SetFileModDate(modDate);
  2795.     file->SetFileCreationDate(creationDate);
  2796. //    file->SetStationery(ODGetSUIsStationery(ev, su));
  2797. }
  2798.  
  2799. static OSErr GetDropFSSpec(ODPlatformDragReference theDrag, FSSpec &dropFSSpec)
  2800. {
  2801.     AEDesc    dropDescriptor;
  2802.  
  2803.     OSErr result = GetDropLocation(theDrag, &dropDescriptor);
  2804.     if ((result != noErr) ||
  2805.         (dropDescriptor.descriptorType == typeNull) ||
  2806.         (dropDescriptor.dataHandle == nil))
  2807.     {
  2808.         result = fnfErr;            // Can't create a file unless we know where it goes!
  2809.     }
  2810.     else
  2811.     {
  2812.         AEDesc fssDescriptor;
  2813.         result = AECoerceDesc(&dropDescriptor, typeFSS, &fssDescriptor);
  2814.         AEDisposeDesc(&dropDescriptor);
  2815.         if (result == noErr) {        
  2816.             ODBlockMove(*fssDescriptor.dataHandle, &dropFSSpec, sizeof(FSSpec));
  2817.             AEDisposeDesc(&fssDescriptor);
  2818.  
  2819.             // Use PBGetCatInfo to get the directoryID of the target directory.
  2820.             CInfoPBRec getInfoPB;
  2821.             getInfoPB.dirInfo.ioCompletion = 0L;
  2822.             getInfoPB.dirInfo.ioNamePtr = (StringPtr) &(dropFSSpec.name);
  2823.             getInfoPB.dirInfo.ioVRefNum = dropFSSpec.vRefNum;
  2824.             getInfoPB.dirInfo.ioFDirIndex = 0;
  2825.             getInfoPB.dirInfo.ioDrDirID = dropFSSpec.parID;
  2826.             result = PBGetCatInfoSync(&getInfoPB);
  2827.             if (result == noErr)
  2828.             {
  2829.                 dropFSSpec.parID = getInfoPB.dirInfo.ioDrDirID;
  2830.                 dropFSSpec.name[0] = 0;
  2831.             }
  2832.         }
  2833.     }
  2834.     
  2835.     return result;
  2836. }
  2837.  
  2838. static boolean IsTrashFolder(FSSpec dropFSSpec)
  2839. {
  2840.     short trashVol;
  2841.     long trashDir;
  2842.  
  2843.     return (FindFolder(dropFSSpec.vRefNum,kTrashFolderType,kDontCreateFolder,&trashVol,&trashDir) == noErr) && 
  2844.             (trashVol==dropFSSpec.vRefNum) && (
  2845.             (trashDir==dropFSSpec.parID) );
  2846.  
  2847. }
  2848.  
  2849. static boolean IsFrontProcess()
  2850. {
  2851.     ProcessSerialNumber myProcess, frontProcess;
  2852.     boolean inFront = false;
  2853.  
  2854.     GetCurrentProcess(&myProcess);
  2855.     GetFrontProcess(&frontProcess);
  2856.     SameProcess(&myProcess, &frontProcess, &inFront);
  2857.  
  2858.     return inFront;
  2859. }
  2860.  
  2861. static OSErr CreateReplaceFileEvent(Environment* ev,
  2862.     AppleEvent* replaceFileEvent,
  2863.     ODSession* session,
  2864.     ProcessSerialNumber* psn)
  2865. {
  2866.     OSErr            err = noErr;
  2867.     AEAddressDesc    targetAddress;
  2868.     TempAEDesc        tempTargetAddress = kODNULL;
  2869.     
  2870.     err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(ProcessSerialNumber), &targetAddress);
  2871.  
  2872.     if (err == noErr)
  2873.     {
  2874.         err = AECreateAppleEvent(kODShellSignature, kODReplaceFileEventID, 
  2875.                 &targetAddress, kAutoGenerateReturnID, 
  2876.                 kAnyTransactionID, replaceFileEvent);
  2877.         AEDisposeDesc(&targetAddress);
  2878.     }
  2879.     if ( err == noErr )
  2880.         err = AEPutParamPtr(replaceFileEvent, kODSession, typeLongInteger,
  2881.                             &session, sizeof(ODSession*));
  2882.     return err;
  2883. }
  2884.  
  2885. static OSErr SetupReplaceFileEvent(Environment* ev,
  2886.     AppleEvent* replaceFileEvent,
  2887.     FSSpec* sourceFileSpec,
  2888.     FSSpec* destFileSpec)
  2889. {
  2890.     OSErr err = noErr;
  2891.     if (err == noErr)
  2892.     {
  2893.         err = AEPutParamPtr(replaceFileEvent, kODSourceFileSpec, typeFSS,
  2894.                         sourceFileSpec, sizeof(FSSpec));
  2895.     }
  2896.     if ( err == noErr )
  2897.         err = AEPutParamPtr(replaceFileEvent, kODDestinationFileSpec, typeFSS,
  2898.                             destFileSpec, sizeof(FSSpec));
  2899.  
  2900. #ifdef ODDebug                    
  2901.     if (err != noErr)
  2902.     {
  2903.         WARN("Error in SetupReplaceFileEvent: %d", err);
  2904.     }
  2905. #endif
  2906.  
  2907.     return err;
  2908. }
  2909.  
  2910. static OSErr SendReplaceFileEvent(AppleEvent* replaceFileEvent, ProcessSerialNumber* psn)
  2911. {
  2912.     OSErr        err;
  2913.     AppleEvent    replyAppleEvent;
  2914.     
  2915.     SetFrontProcess(psn);
  2916.     
  2917. //    TempAEDesc tmpReplaceFileAppleEvent(replaceFileEvent);
  2918.     err = AESend(replaceFileEvent, &replyAppleEvent, kAENoReply | kAEInteractWithSelf,
  2919.                         kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  2920.  
  2921. #ifdef ODDebug                    
  2922.     if (err != noErr)
  2923.     {
  2924.         WARN("Error in SendReplaceFileEvent: %d", err);
  2925.     }
  2926. #endif
  2927.                             
  2928.     return err;
  2929. }
  2930.  
  2931. static OSErr DisposeReplaceFileEvent(AppleEvent* replaceFileEvent)
  2932. {
  2933.     return AEDisposeDesc(replaceFileEvent);
  2934. }
  2935.  
  2936. static OSErr ODPascal ReplaceFileAEHandler(
  2937.         const AppleEvent* replaceFileEvent,
  2938.         AppleEvent* reply,
  2939.         long refCon)
  2940. {
  2941.     OSErr        err = noErr;
  2942.     DescType    returnedType;
  2943.     Size        actualSize;
  2944.     FSSpec        sourceFileSpec;
  2945.     FSSpec        destFileSpec;
  2946.     ODSession*    session = kODNULL;
  2947.     
  2948.     err = AEGetParamPtr(replaceFileEvent, kODSession,
  2949.                             typeLongInteger, &returnedType,
  2950.                             &session, sizeof(ODSession*), &actualSize);
  2951.     WASSERTM(actualSize == sizeof(ODSession*), "Incorrect kODSession size");
  2952.     
  2953.     if (err == noErr)
  2954.     {
  2955.         err = AEGetParamPtr(replaceFileEvent, kODDestinationFileSpec,
  2956.                                 typeFSS, &returnedType,
  2957.                                 &destFileSpec, sizeof(FSSpec), &actualSize);
  2958.         WASSERTM(actualSize == sizeof(FSSpec), "Incorrect DestinationFileSpec size");
  2959.     }
  2960.     
  2961.     if (err == noErr)
  2962.     {
  2963.         Environment* ev = somGetGlobalEnvironment();
  2964.         ParamText(destFileSpec.name, "\p", "\p", "\p");
  2965.         err = AEInteractWithUser(kAEDefaultTimeout, NULL, NULL);
  2966.         if ((err == noErr) && ODAskUserReplace(ev, session))
  2967.         {
  2968.             err = AEGetParamPtr(replaceFileEvent, kODSourceFileSpec,
  2969.                                     typeFSS, &returnedType,
  2970.                                     &sourceFileSpec, sizeof(FSSpec), &actualSize);
  2971.             if (err == noErr)
  2972.             {
  2973.                 WASSERTM(actualSize == sizeof(FSSpec), "Incorrect kODSourceFileSpec size");
  2974.                 TempPlatformFile sourceFile = new PlatformFile;
  2975.                 sourceFile->Specify(&sourceFileSpec);
  2976.                 TempPlatformFile destFile = new PlatformFile;
  2977.                 destFile->Specify(&destFileSpec);
  2978.                 
  2979.                 destFile->MoveToTrash();
  2980.                 sourceFile->Move(destFileSpec.parID);
  2981.             }
  2982.         }
  2983.     }
  2984.  
  2985. #ifdef ODDebug
  2986.     if (err != noErr)
  2987.         WARN("Error occured in ReplaceFileAEHandler: %d", err);
  2988. #endif
  2989.  
  2990.     return err;
  2991. }
  2992.  
  2993. static void RespecifyToTempFolder(PlatformFile* file)
  2994. {
  2995.     ODSLong    tempDirID;
  2996.     FSSpec    fsSpec = file->GetFileSpec();
  2997.     
  2998.     THROW_IF_ERROR(FindFolder(fsSpec.vRefNum, kTemporaryFolderType, kCreateFolder,
  2999.                             &(fsSpec.vRefNum), &tempDirID));
  3000.     fsSpec.parID = tempDirID;
  3001.     file->Specify(&fsSpec);
  3002.     if (file->Exists())
  3003.         file->Delete();
  3004. }
  3005.  
  3006. static ODBoolean IsOpenDocDocument(HFSFlavor* hfsFlavor)
  3007. {
  3008.     return PlatformFile::IsOpenDocDocument(hfsFlavor->fileType,hfsFlavor->fileCreator);
  3009. }
  3010.  
  3011. static ODBoolean IsOpenDocClipping( HFSFlavor* hfsFlavor) 
  3012. {
  3013.     ODBoolean isOpenDocClipping = kODFalse;    
  3014.     OSType theFileType = hfsFlavor->fileType;
  3015.     
  3016.     // Check if the clipping came from the drag manager.
  3017.     if( hfsFlavor->fileCreator == 'drag' )
  3018.     {
  3019.         // Now check if it has the file type 'clp≈' where ≈ is any lower case letter.
  3020.         ODUByte* tempPtr = (ODUByte*)&theFileType;
  3021.         if( ( tempPtr[0] == 'c' ) && ( tempPtr[1] == 'l' ) &&
  3022.             ( tempPtr[2] == 'p' ) && ( islower( tempPtr[3] ) ) )
  3023.         {
  3024.             OSErr theErr;
  3025.             short oldResRefnum;
  3026.             short clippingRefNum;
  3027.             ODHandle tempHandle = kODNULL;
  3028.             
  3029.             // Now check if there is a resource of type kODBentoFlavor
  3030.             oldResRefnum = CurResFile();
  3031.             // Open the clipping's resource fork.
  3032.             SetResLoad(false);        // Inside Mac says to make the SetResLoad calls before & after the OpenResFile call.
  3033.                                     // We probably don't need to do this in our case, but I'm paranoid today.
  3034.             clippingRefNum = FSpOpenResFile(&(hfsFlavor->fileSpec), fsCurPerm);
  3035.             SetResLoad(true);
  3036.             theErr = ResError();
  3037.             if( theErr == noErr )
  3038.             {
  3039.                 short numODCN = Count1Resources(kODBentoFlavor);
  3040.                 if( numODCN ==1 )        // the clipping has the Bento container data
  3041.                     isOpenDocClipping = kODTrue;
  3042.                 CloseResFile( clippingRefNum );
  3043.             }
  3044.             SetResLoad(true);        
  3045.             UseResFile(oldResRefnum);
  3046.         }
  3047.     }
  3048.     
  3049.     return isOpenDocClipping;
  3050. }
  3051.  
  3052. static ODHandle ReadOpenDocDataFromClippingFile( HFSFlavor* hfsFlavor )
  3053. {
  3054.     OSErr theErr;
  3055.     short oldResRefnum;
  3056.     short clippingRefNum;
  3057.     ODHandle tempHandle = kODNULL;
  3058.     
  3059.     oldResRefnum = CurResFile();
  3060.     // Open the clipping's resource fork.
  3061.     SetResLoad(false);        // Inside Mac says to make the SetResLoad calls before & after the OpenResFile call.
  3062.         clippingRefNum = FSpOpenResFile(&(hfsFlavor->fileSpec), fsCurPerm);
  3063.     SetResLoad(true);        // We probably don't need to do this, but I'm paranoid today.
  3064.     theErr = ResError();
  3065.     if( theErr == noErr )
  3066.     {                                
  3067.         // The clipping has the data in a resource of the same name as the drag flavor, which
  3068.         // in our case is the the constant kODBentoFlavor.
  3069.         tempHandle = (ODHandle)ODReadResourceUsingRefnum( clippingRefNum, kODBentoFlavor, 1, kODNULL,1 );
  3070.         CloseResFile( clippingRefNum );
  3071.     }
  3072.     if( theErr != noErr )
  3073.     {
  3074.         UseResFile(oldResRefnum);
  3075.         THROW( theErr );
  3076.     }
  3077.     
  3078.     UseResFile(oldResRefnum);
  3079.     return tempHandle;
  3080. }
  3081.